Обзор эксплойтовКрис Касперски Критические ошибки обнаруживаются в Windows едва ли не каждую неделю, но глобальные эпидемии возникают, прямо скажем, не часто. Последняя нашумевшая уязвимость относится к ветхозаветной дыре в службе RPC DCOM, эксплуатируемой червем MSBlast. И вот, наконец, новая дыра и новый червь, распространяющийся со скоростью лесного пожара — Gimmiv! А за ним – руткит KernelBot.dg, плюс толпа всякой мелкой малвари до кучи. Встречайте аплодисментами! MS Windows – локальное разрушение памяти ядраBriefВ конце ноября 2008 года австрийский хакер Thomas Unterleitner из компании phion AG совместно с коллегами по цеху (Marius Wachtler, Michael Burgbacher, Carson Hounshell и Michael Craggs) обнаружили переполнение буфера в TCP/IP-стеке Висты. По горячим следам они опубликовали статью «Microsoft VISTA TCP/IP stack buffer overflow», описывающую ужасные последствия стекового переполнения и тут же подхваченную журналисткой общественностью. На самом деле, «TCP/IP-стек» не более чем метафора. Переполняющийся буфер расположен в куче, выделяемой ядерной функцией ExAllocatePoolWithTag, тупо аллоцирующей 32 байта без проверки реальной длины передаваемых данных (поставляемых документированной API-функцией CreateIpForwardEntry2, экспортируемой библиотекой iphlpapi.dll, входящей в штатную поставку как 32-битной, так и 64-битной версий Windows Vista…). Согласно MSDN, функция принимает структуру MIB_IPFORWARD_ROW2, включающую в себя поле PrefixLength и определяющую размер префикса с максимально допустимой длиной в 32 байта (по документации). В реальности же, PrefixLength представляет собой DWORD, передаваемый функции memcpy. Это позволяет перезаписывать ядерную память с прикладного уровня. Последствием будет либо голубой экран смерти, либо передача управления на shell-код. Поскольку вызов CreateIpForwardEntry2 требует администраторских прав, достаточно многие эксперты по безопасности недооценивают угрозу, полагая, что злоумышленник, обладающий правами администратора, может «поиметь» систему и без переполнения (загрузить вредоносный драйвер, например). Вот только 64-битные версии Windows без цифровой подписи драйвер ни за что не загрузят, а потому даже локальные дыры ядра приобретают особую актуальность. Кстати говоря, не устраняемую установкой Service Pack 1! 64-битные версии XP также требуют обязательной цифровой подписи, но ошибки переполнения MIB_IPFORWARD_ROW2. PrefixLength в них нет, как нет ее и в Server 2003. А все потому, что сетевой стек Висты был переписан с нуля, и ошибок там... В общем, это не первая, и уж точно не последняя дыра. От глобальных потрясений нас спасает лишь непопулярность Висты, обуславливающая не только малое количество уязвимых машин, но и нежелание хакеров тратить время на поиск дыр, которые все равно не удастся использовать в «промышленных» масштабах. Ну, разве что в образовательных целях. Желающие поэкспериментировать найдут все необходимую техническую информацию на securityfocus.com/archive/1/498471. TargetsVista Home/Business/Enterprise/Ultimate x32/x64 SP0/SP1 ExploitИсходный текст exploit'а, написанного на Си и вызывающего обрушение системы в голубой экран смерти, можно найти в статье Thomas'a Unterleitner'a или скачать с securityfocus.com/data/vulnerabilities/exploits/32357.c. Ключевой фрагмент программы приводится ниже. Жестко прошитые IP-адреса руками не трогать! Атака носит локальный характер и за пределы узла-источника пакеты все равно не уходят. Так что IP-адреса на суть дела никак не влияют. Ключевой фрагмент exploit'а, вызывающего разрушение ядреной памяти Висты
SolutionMicrosoft все еще не подтвердила атаку, а потому заплаток нет, и вряд ли скоро будет. В принципе, ядро не сложно отпачить и руками, воткнув туда недостающую проверку, но особого смысла в этом мало. Проще не сидеть под администратором. MS Windows – локальный отказ в обслуживанииBriefЕще один дефект ядра, затрагивающий Висту, был обнаружен хакером по кличке support#killprog.com. Одновременный вызов API-функции UnhookWindowsHookEx (снятие глобального хука) с переключением Рабочего Стола (за что отвечает API-функция SwitchDesktop) приводит к падению драйвера win32k.sys, выбрасывающего голубой экран смерти. Причем, обе API-функции доступны непривилегированным пользователям! Это создает существенную угрозу для безопасности всей системы в целом. Той самой системы, надежность которой (если верить Руссиновичу) от переноса графической подсистемы в драйвер уровня ядра ничуть не пострадала. Наверное, Руссинович не читал Законов Мерфи. Применительно к exploit'у, выпущенному support#killprog'ом, хочу сказать, что одновременность вызова API-функций там обеспечивается путем отдачи процессорных квантов посредством Sleep(0) — вот такой хитроумный способ межпоточной синхронизации. А потоков exploit создает ровно четыре штуки. Следовательно, на четырех ядерной системе все потоки стартуют одновременно (ну, практически одновременно) и отдавать кванты становится уже некому. Для повышения стабильности работы exploit'а количество создаваемых потоков рекомендуется увеличить в несколько раз, иначе Windows обидится и не упадет. О причинах падения можно прочитать на murphy-law.net.ru и securityfocus.com/bid/32206. TargetsДефект подтвержден в Server 2003 Standard/Enterprise/Datacenter x32/x64 и Vista Home/Premium/Ultimate x32/x64. Другие версии не проверялись, но есть все основания полагать, что они также уязвимы. ExploitИсходный текст exploit'а, написанный на приплюснутом Си, можно найти на securityfocus.com/data/vulnerabilities/exploits/whk.zip — в архив входит файл проекта Microsoft Visual C++ и откомпилированный exe/dll (динамическая библиотека необходима для организации хуков). SolutionА нету! Во всяком случае, Microsoft хранит гробовое молчание — ни бюллетеней безопасности, ни заплаток. Приходится починять систему самостоятельно, поскольку дефект проявляется не только при атаке, но и в результате нормальной эксплуатации — хуки устанавливают достаточно многие приложения (драйвера мультимедийных клавиатур, например). Они же поддерживают более одного рабочего стола, при активной работе с которым проблема встает в полный рост. Свой собственный Server 2003 я пофиксил путем горячего патча USER32.DLL в памяти, воткнув в начало функции UnhookWindowsHookEx проверку на вхождение SwitchDesktop с ожиданием выхода из последнего. Opera – локальное переполнение кучиBriefКоличество дыр, обнаруженных в Опере, неуклонно растет. Помимо тривиального отказа в обслуживании (которым сегодня никого не удивишь), встречаются и критические ошибки, допускающие удаленное выполнение shell-кода. Самая свежая уязвимость подобного рода датируется ноябрем 2008 года и относится к переполнению кучи при задании слишком длинного адреса (прядка ~16,500 символов) в URL типа file. И хотя на Security Focus (смотри securityfocus.com/bid/32323) дыра описывается как удаленная, переполнение происходит только при локальном открытии HTML-файла с кодом exploit'а. Однако, если жертва сохранит страничку на диск, чтобы позднее просмотреть ее offline, локальная атака тут же превратится в удаленную. Учитывая, что странички сохраняются не так уж редко, угроза атаки достаточно велика. Впрочем, малая распространенность Оперы служит надежной защитой :). TargetsУязвимость подтверждена в Опере 9.6 и 9.62. ExploitИсходный текст exploit'а, вызывающего «Калькулятор», можно найти на milw0rm.com/exploits/7135, а ниже приведен его ключевой фрагмент. Код exploit'а, атакующего Оперу
SolutionНесмотря на то, что разработчики Оперы были уведомлены первооткрывателем дыры еще в сентябре, никакой реакции от них не последовало. Лекарства нет, и когда оно появится – неизвестно. MS Windows – удаленное переполнение буфера в RPCBrief2 ноября 2008 года червь Морриса (исходные коды которого до сих пор хранятся в Бостонском Музее Науки) отметил свой 20-летний юбилей. И как раз в то же время вспыхнула новая масштабная эпидемия, распространяющаяся через дыру в службе RPC. Затрагивает она все системы от Windows 2000 до Висты/Server 2008 включительно и позволяет забросить на целевую машину зловредный код безо всякой аутентификации. Уязвимости подвержены как 32-битные, так и 64-версии, что создает крайне благоприятные условия для размножения червей. Trojan-Spy:W32/Gimmiv.A/B/C, W32/Conficker.worm, Trojan:Win32/Wecorl.A/B, Trojan:Win32/ Clort.A/!exploit/dr, TrojanDownloader:Win32/VB.CQ/CJ – вот неполный список заразы, известной на данный момент, и этот список неуклонно растет. Большое количество публичных exploit'ов существенно облегчает жизнь вирусописателей, которым достаточно просто выдрать атакующий код и вставить его в свой проект, написанный на любом языке даже без знания ассемблера. И хотя Microsoft уже выпустила «лекарство», а поставщики систем обнаружения вторжений добавили в базы новые сигнатуры, описывающие основные вектора атаки (без привязки к конкретным вирусам), хакерские атаки захлебываться не собираются! Патч от Microsoft фиксит только часть дыр, а существующие сигнатуры обходятся на ура (чуть позже мы покажем, как это сделать). Короче, ситуация очень серьезна и заслуживает самого тщательного анализа. Как обычно, официальные источники содержат только обрывки информации: microsoft.com/technet/security/Bulletin/ms08-067.mspx, securityfocus.com/bid/31874, http://blogs.technet.com/swi/ и blogs.msdn.com/sdl/archive/2008/10/22/ms08-067.aspx. TargetsУязвимость затрагивает всю линейку NT-подобных систем: W2K Professional/ Server/Advanced/Datacenter SP0/SP1/SP2/SP3/SP4, XP Gold/Home/Professional SP0/SP1/ SP2/SP3 x86/x86-64, Vista Home/Business/ Enterprise/ Ultimate SP0/SP1 x86/x86-64, S2K3 Standard/Datacenter/Advanced/Enterprise SP0/SP1/SP2 x86/x86-64/ Itanium, S2K8 Standard/Datacenter/Advanced/Enterprise SP0 x86/x86-64/ Itanium. ExploitsГотовых exploit'ов много, рабочих же среди них... ну не то, чтобы нет совсем, но очень мало, да и те нуждаются в исполняемом стеке или работают лишь с известными им операционными системами (W2K, XP, S2K3). Под Висту и S2K8 боевых exploit'ов в открытом доступе пока нема, но я покажу, как их написать! А писать мы их будем на основе уже существующего кода, ссылки на который приведены ниже:
SolutionMicrosoft выпустила заплатки для всех операционных систем, но исправила лишь часть ошибок, а потому установка пакета обновления (который можно добыть на microsoft.com/technet/security/Bulletin/ms08-067.mspx) блокирует только первое поколение червей, но не спасает против целевых атак. Закрытие 139 и 445 портов на брандмауэре надежно защищает нас от вторжения, но разделяемые ресурсы при этом становятся недоступными. Приходится не по-детски извращаться, создавая сложные правила фильтрации трафика, основанные на поиске последовательностей «5c 00 2e 00 2e 00 5c 00» («\..\»), «2f 00 2e 00 2e 00 2f 00» («/..»), «5c 00 2e 00 2e 00 2f 00» («\../») и «5c 00 2e 00 2e 00 2f 00» («/..\»). Ну а для тестирования брандмауэра можно воспользоваться моей утилитой (kpnc.org/ftp/MS08-067.zip, пароль «123456»). Она инсценирует атаку на RPC и выбрасывает внутри сервиса SRVSVC необрабатываемое исключение, приводящее к его гибели (вместе с дырой). Правильно сконфигурированный брандмауэр блокирует посылку пакетов, и сервис продолжает работать даже после запуска программы. DiscloseА сейчас мы будем хакерствовать, демонстрируя методики скоростного поиска дыр и исправления ошибок в вирусах/exploit'ах. Ведь мы же хотим атаковать не только хрюшу, установленную на древнем ЦП с исполняемым стеком, но и современные системы, верно? А как будем атаковать? Притворимся, что мы ничего не знаем о дыре — типа никаких статей не читали, червей не дизассемблировали и даже исходные тексты exploit'ов не листали. Представим, что у нас есть только бюллетень безопасности от Microsoft, из которого ничего понять невозможно. Типа, где-то там в RPC есть дыра, но что за дыра, и где именно ее искать — кто же нам это скажет! Ничего не остается, кроме как запасаться пивом и добывать недостающую информацию самостоятельно. Самое простое — скачать «заплатку» от Microsoft и посмотреть, что именно было исправлено, сравнив ее с непатченным оригиналом. Различные системы имеют различные дыры, и потому для полноты картины необходимо исследовать все заплатки, начиная с W2K и заканчивая S2k8. Поскольку техника анализа во всех случаях полностью идентична, продемонстрируем ее на примере W2K, обновление для которой упрятано в исполняемый файл Windows2000-KB958644-x86-RUS.EXE, представляющий собой самораспаковывающийся CAB-архив. Как добыть из него актуальные файлы? Загружаем exe в HIEW, ищем сигнатуру «MSCF». После чего выделяем блок и копируем его в .cab, распаковываемый штатной Windows-утилитой compress.exe либо RAR'ом, извлекающим на свет божий netapi32.dll, в которой и сосредоточены все исправления. Примечание: для XP данная техника уже не работает, но можно схитрить — запустить exe без прав администратора и, получив сообщение об ошибке, вытащить распакованные инсталлятором файлы из временной папки. Затем нажать на «ОК», позволяя инсталлятору удалить их обратно. Теперь нам потребуется IDA-Pro и утилита для сравнения патчей — коммерческий BinDiff или же бесплатный PatchDiff, причем качество последнего ничуть не хуже, и я им вполне доволен: http://cgi.tenablesecurity.com/tenable/patchdiff.php. Переименовываем оригинальный netapi32.dll в netapi32_o.dll, грузим в IDA-Pro и дожидаемся завершения дизассемблирования. Закрываем базу, загружаем исправленный netapi32.dll (переименованный в netapi32_p.dll), дизассемблируем, после чего лезем в меню Edit\Plug-ins, находим там PatchDiff и указываем ему netapi32_o.idb. На удивление, PatchDiff генерирует довольно чистый отчет, содержащий всего 21 функцию. Практически все функции несут на своем борту актуальные изменения, которые удобнее всего просматривать в графическом режиме (контекстное меню -> пункт «Graph»). В частности, сравнение оригинальной и пропатченной функции «I_NetPathCanonicalize» выглядит так (смотри рисунок). Измененный код находится в красных блоках. Чтобы их увеличить — жмем «1». Чтобы перейти к дизассемблерному коду — щелкаем правой кнопкой мыши и выбираем пункт «Jump to Code» в контекстом меню. Оригинальная netapi32.dll Пропатченная netapi32.dll Ага! В оригинальной версии вызывается функция NetpIsRemote(Buffer, int, Dest, char), а в исправленной — NetpIsRemote(Buffer, int, Dest, char, 0x104). Как нетрудно догадаться, 0x104 — максимально допустимый размер буфера, предотвращающий переполнение. Остается только выяснить, где происходит переполнение. А происходит оно в функции NetpwPathCanonicalize(), вызывающей в свою очередь функцию sub_7CD1AB28, ключевой фрагмент которой приведен ниже: Уязвимый код, вызывающий переполнение буфера В глаза сразу бросается «сладкая парочка» — wcslen()/wcscpy(). Она характерна для bug-free программ, но в нашем случае явная проверка длины строки перед копированием от переполнения не спасает, поскольку функция ищет символы «/», «\» и «.», удаляя последовательности а-ля «\..\» и ошибаясь в коррекции размеров буфера: Функция «нормализации» сетевых имен Как следствие, уязвимость распространяется на все функции, вызывающие sub_7CD1ABD9() для нормализации имен. Таких функций достаточно много. Существующие черви и exploit'ы используют всего два метода службы SRVSVC – I_NetPathCanonicalize и I_NetPathCompare. Однако, в нашем распоряжении есть другие. Вот полный список уязвимых методов, доступных для непосредственного вызова через сетевой интерфейс 4B324FC8-1670-01D3-1278-5A47BF6EE188:
Для эксплуатации уязвимости необходимо внедрить в сетевое имя (передаваемое функции в качестве аргумента) последовательность «\..\» или же что-нибудь в этом роде – «/../», «/..\», «\../» (последние две конструкции поддерживает только S2k3/S2k8). Механизм вызова методов обозначенного сетевого интерфейса долгое время оставался недокументированным, и хакерам приходилось терзать исходные тексты Самбы. Теперь же достаточно сходить на MSDN, где выложены примеры взаимодействия со службой SRVSVC и описаны опкоды некоторых методов: msdn.microsoft.com/en-us/library/cc213209.aspx. Попытка найти недостающие опкоды в неофициальной документации (hsc.fr/ressources/articles/win_net_srv/msrpc_srvsvc.html) также не дает результата. Ну не дает – и не надо! Нам хватит и документированных функций. Чтобы реализовать атаку, необходимо решить две проблемы — передать управление на shell-код и обойти защиту от исполнения кода в стеке. В классическом варианте задача решается путем помещения в адрес возврата указателя на инструкцию JMP ESP/CALL ESP (FFE4h/FFD4h), которую можно найти как в netapi32.dll, так и в остальных системных библиотеках. Естественно, адреса привязаны к конкретной версии Windows, что делает атакующий код непереносимым. Однако можно найти и такие последовательности байт, которые справедливы более чем для одной версии операционной системы. Достаточно воспользоваться онлайновым мастером, «крышуемым» Metaspoit'ом. Но это будет работать при выключенном DEP'е, а у большинства пользователей он включен, и для борьбы с защитой приходится заносить в стек адреса API-функций типа VirtualAlloc или VirtualProtect создающие блоки с атрибутами «исполняемый» (подробности — в Google по запросу return2libc). Точить свой exploit с абсолютного нуля — необязательно. Проще доработать уже имеющиеся. Естественно, для этого нужно не только знать Си и/или Питон, но и разбираться в shell-кодах, что и представляет основную проблему. А ключевой фрагмент эксплойта ты можешь найти на нашем DVD. |