Различия

Здесь показаны различия между двумя версиями данной страницы.

Ссылка на это сравнение

articles:exploits-review-0x16 [2017/09/05 02:55] (текущий)
Строка 1: Строка 1:
 +====== exploits-review-0x16 ======
 +<​sub>​{{exploits-review-0x16.odt|Original file}}</​sub>​
 +
 +====== exploits review\\ 16h выпуск ======
 +
 +крис касперски ака мыщъх, a.k.a. nezumi, a.k.a elraton, a.k.a. souriz, no-email
 +
 +**чем глубже в ****windows****,​ тем больше дыр, поток которых прекращается не собирается,​ отрывая весьма соблазнительные перспективы для хакерских атак, как локальных,​ так и удаленных,​ к которым ни ****Microsoft****,​ ни сторонние разработчики не готовы и которым придется конкретно напрячься,​ чтобы разрулить ситуацию,​ а мы к тому времени нароем новые дыры, так что никто без работы не останется.**
 +
 +===== Microsoft Windows – unicast/​multicast traffic and firewalls =====
 +
 +**brief**:​экспериментируя с программами потокового аудио/​видео вещая (главным образом с VideoLAN), мыщъх с удивлением обнаружил,​ что его любимый SyGate Personal Firewall 4.5 в упор не видит ни входящего,​ ни исходящего unicast/​multicast трафика и, соответственно,​ не может заблокировать его, что очень странно и подозрительно,​ особенно в случае с unicast-трафиком,​ работающий поверх IP и с этой точки зрения ничем не отличающихся от прочих IP-пакетов. Но тем не менее факт! Очень упрямый и труднообъяснимый. Беглое расследование показало,​ что начиная еще с NT 4.0 и NT 3.51 SP2,​ обработка unicast/​multicast-потоков выделена в отдельное "​делопроизводство"​ внутри сетевой подсистемы. Мотивы вполне ясны и особенно хорошо ощутимы на "​тонких"​ каналах связи. "​Выхватывая"​ unicast/​multicast пакеты из общего сетевого трафика,​ операционная система уделяем максимум внимания,​ оттесняя весь остальной TCP/​IP-трафик на второй план. Другими словами,​ чтобы не реализовывать приоретизированный сетевой ввод/​вывод,​ разработчики Windows, сделали исключение лишь для unicast/​multicast-трафика,​ обрабатываемого с максимальным приоритетом. Кстати,​ чтобы выяснить это, совершенно необязательно иметь секс с отладчиком и дизассемблером — достаточно раскурить MSDN: technet2.microsoft.com/​windowsserver/​en/​library/​3da7c55f-cb91-406a-8596-7b120ebf10f81033.mspx?​mfr=true,​ там же можно нарыть и примеры создания IP-фильтров,​ учитывающих весь трафик:​ www.microsoft.com/​technet/​prodtechnol/​windows2000serv/​reskit/​intwork/​inae_ips_neez.mspx?​mfr=true,​ в том числе и unicast/​multicast,​ и тогда ни один пакет не пройдет незамеченным. Увы! Далеко не все разработчики персональных брандмауэров учитывают это обстоятельно,​ что позволяет хакерам генерировать unicast трафик и пускать его в обход брандмауэра;​
 +
 +targets:NT 3.51 SP2 и выше, SyGate Personal Firewall 4.5 и некоторые другие брандмауэры;​
 +
 +exploits:в качестве "​тестера",​ определяющего способность брандмауэра распознавать и блокировать различные виды unicast/​multicast трафика можно использовать беспоатную программу VidoeLAN, кстати говоря,​ распространяемую в исходных текстах:​ www.videolan.org;​
 +
 +solution:​использовать в качестве шлюза для доступа в Сеть любую Linux или BSD-подобную систему,​ чей штатный брандмауэр влет бьет любой unicast/​mulicast трафик;​
 +
 +{{exploits-review-0x16_Image_0.png?​553}}
 +
 +Рисунок 1 внешний вид программы VideoLAN
 +
 +===== Microsoft Windows – обход ASLR =====
 +
 +brief:в Висле появилась рандомизация адресного пространства,​ существенно затрудняющая внедрение зловредного кода в "​доверенные"​ процессы,​ типа explorer.exe,​ которым разрешен выход в сеть. Классическая схема внедрения (VirtualAllocEx,​ WriteProcessMemory,​ SetThreadContext) распознается практически всеми антивирусами и персональными брандмауэрами,​ написанными еще много лет тому назад, поэтому хакеры усовершенствовали методику,​ отказавшись от функции SetThreadContext,​ посредством которой они ранее изменяли регистр EIP так, чтобы он указывал на внедренный код. В новой схеме передача управления осуществлялась путем заполнения стека главного потока (благо,​ его местоположение вплоть до Вислы оставалось постоянным) указателями на внедренный код. Поскольку,​ комбинация команд VirtualAllocEx/​WriteProcessMemory довольно распространена среди "​честных"​ программ и представляет собой совершенно легальный механизм межпроцессорного взаимодействия,​ то никакие защиты на нее не ругаются. Но с появлением Вислы ситуация изменилась и базовый адрес стека стал располагаться по случайным адресам,​ что должно было положить конец хакерству,​ но… так и не положило,​ поскольку,​ существует такая замечательная API-функция как VirtualQueryEx,​ возвращающая карту памяти целевого процессаи не менее замечательная API-функция VirtualProtectEx,​ сообщающая атрибуты страницы. Так вот, стек представляет собой блок памяти,​ на вершине которого лежит страница с атрибутами PAGE_GUARD, что является его характерной чертой,​ позволяющей отличать стек от всех остальных регионов памяти (примечание:​ некоторые программы так же пользуются флагом PAGE_GUARD для динамического выделения памяти,​ но очень и очень немногие).Важно понять,​ что PAGE_GUARD определяет не текущее значение регистра ESP, а самое высокое положение указателя вершины стека, когда либо достигнутое потоков в процессе его существования. Реальное же значение ESP как правило _намного_ ниже, но что нам стоит заполнить указателями на внедренный нами код _весь_ блок от PAGE_GUARD и до его конца?​! Кстати говоря,​ поскольку операционная система выделяет стек постранично и делает это через общий с кучей менеджер памяти,​ то функцией VirtualFreeEx мы можем освобождать страницы,​ принадлежащие стеку одному из потоков целевого процесса,​ возвращая их в общий пул свободной памяти и тогда… куча окажется прямо в стеке! И программа,​ пытаясь прочитать локальные переменные или стянуть адрес возврата из функции встретит что-то очень неожиданное и скорее всего рухнет,​ если, конечно,​ мы не подложим в строго определенные места заданные указатели,​ передающие управления на внедренный нами код. При желании можно придумать и другие разновидности атак на эту тему, но уже и без того ясно, что ASLR никакая не защита,​ а так… пугало для пионеров;​
 +
 +
 +
 +targets:​Висла/​Server 2008 (в более ранних системах рандомизация адресного пространства отсутствует,​ но данная атака прекрасно совместима с ними, включая линейку 9x);
 +
 +exploit:​не требуется,​ любой отладчик (например,​ Olly) без труда найдет стек основного потока в целевом процессе по карте памяти;​
 +
 +solution:​отсутствует;​
 +
 +{{exploits-review-0x16_Image_1.png?​553}}
 +
 +Рисунок 2 на вершине блока памяти,​ выделенного потоку,​ гордо возлегает страница с атрибутами PAGE_GUARD (ну или Guarded – в терминах OllyDbg)
 +
 +===== Microsoft Windows – ошибка подсчета квотирования =====
 +
 +brief:в W2K (с большой задержкой против UNIX) наконец-то появилась поддержка квотирования дискового пространства,​ позволяющая администраторам умерять "​аппетит"​ прожорливых пользователей. Ну а кому понравится,​ когда ограничивают его свободу?​ Вот хакеры и взбунтовались и начали пакостить,​ обходя ограничения и поглощая все доступное дисковое пространство,​ приводящее к невозможности создания новых файлов и — как следствие — краху системы еще на ранних стадиях загрузки (при условии,​ что пользователям разрешено создавать файлы хотя в одном из каталогов системного тома, например,​ Documents-n-Setting или C:​\WINDOWS\TEMP). Разработчики Windows, казалось бы, предусмотрели все, считая сколько физических кластеров занимают все созданные данными пользователем файлы (а для упакованных файлов берется их полный,​ а не сжатый размер). Но один маленький финт ушами они все-таки пропустили. Вопрос,​ мучавший хакеров еще со времен MS-DOS – сколько занимает файл нулевой длины? Ноль байт? Один кластер?​ Или… На самом деле, система не настолько глупа, чтобы выделять дисковое пространство файлу с нулевой длиной и потому формально их можно создавать сколько угодно. Вот только… У файла есть имя, атрибуты,​ дата и время создания,​ идентификатор владельца — словом достаточно большое количество информации,​ которое где-то надо хранить. В NTFS оно хранится в специальном служебном файле с именем $MFT, где на каждый файл заведена специальная файловая запись — структура данных известная как FILE_RECORD,​ размер которой обычно занимает 1 Кб ("​обычно"​ — потому что из этого правила слишком много исключений,​ которые лень перечислять,​ да и на исход дела они _никак_ не влияют,​ так зачем же углубляться в ненужные технические подробности?​). К тому же, для ускорения типовых файловых операций,​ содержимое директорий проиндексировано,​ а каждый индекс тоже пространства хочет (правда,​ не 1 Кб, а намного меньше,​ но все-таки…). Создание пустых файлов в бесконечном цикле вызывает рост $MFT файла, размер которого в пользовательских квотах не учитывается и через некоторое (впрочем,​ довольно продолжительное) время, $MFT поглощает все свободное пространство на диске, затем кончаются файловые записи,​ принадлежащие удаленным файлам и… все. Чтобы создать еще хоть один файл, нужно удалить что-нибудь,​ и успеть опередить хакерский цикл, упорно пытающийся создавать новые файлы…
 +
 +target:W2K и выше (в NT 3.x/4.x нет квот, но данная схема атаки применима и для них).
 +
 +exploit:​ниже приведен исходный код боевого exploit'​а,​ написанного на языке Си и создающего файлы нулевого размера в бесконечном цикле:
 +
 +int a; FILE *f;char buf[256];
 +
 +
 +
 +for (;;)
 +
 +{
 +
 +sprintf(buf,"​%04Xh-%04Xh-%04Xh-%04Xh-%04Xh-%04Xh",​
 +
 +rand(),​rand(),​rand(),​rand(),​rand(),​rand());​
 +
 +f = fopen(buf,"​wb"​);​ if (f) fclose(f);
 +
 +
 +
 +Листинг 1 exploit,​ обходящий систему дисковых квот в W2K и более старших системах
 +
 +solution:​отсутствует;​
 +
 +{{exploits-review-0x16_Image_2.png?​553}}
 +
 +Рисунок 3 сколько байт занимает файл с нулевой длинной?​
 +
 +===== full disclose\\ небезопасный SafeSEH =====
 +
 +28 декабря 2007 года в 5:47 PM мыщъх получил от легендарного во всех отношениях хакера Юрия Харона следующее письмо (приводимое,​ естественно,​ с его разрешения):​
 +
 +"//​Нашел я ошибку в форточках. Слов нет одни эмоции :(. Добавляя новую "​защиту"​ они умудрились (будут интересны подробности — расскажу) оставить _не_проинициализированные_ переменные (правка,​ в крайне экзотической ситуации) в результате чего отваливаем на BSOD при SEH в некоторых (старых) драйверах. Убббивать... Три дня угробил на поиск :(((//
 +
 +//​Теперь эта прошла и вылезла следующая. Которую я обнаружил совершенно случайно — нет, ну вот как так можно?​! Два варианта ntkrnlpa.exe. Версия одна и та же. Билд один и тот же. Но в ////version info//// присутствует строка (////​см. листинг 2////​) и разные они даже по размеру////://​
 +
 +//VALUE "​FileVersion",​ "​5.1.2600.3093 ​ (xpsp_sp2_gdr.070227-2254) ////​////​это в одном//​
 +
 +//VALUE "​FileVersion",​ "​5.1.2600.3093 ​ (xpsp_sp2_qfe.070227-2300) ////​////​это в другом//​
 +
 +//​Листинг////​ ////​2////​ ////​разные строки ////​FileVersion ////в одинаковых билах хрюши//​
 +
 +//При этом (заметим в скобках) _оба_ файлы получены с ////windows update ////​просто один обновился сразу же, как только вышел (в июне-июле),​ а второй только сейчас (на варю когда ставил). Файлы разные даже по размеру (не говоря уж про все остальное). И вот на том который "​сейчас"​ ошибка и вылезла. Причём опять какая-то наведенка :(//
 +
 +//​Интересно сколько я её искать буду...//"​. Мыщъх сказал,​ что подробности,​ разумеется интересны и тут же получил ответ: "//​Напомни завтра(/​ночью) — я щас уже офигел и спать пошел. И, вообще,​ может ты напоминая на старые вопросы ответишь :) Пока (что бы писать меньше) почитай про ключ /SAFESEH в текущем ms-link (не столько про ключ, сколько про то зачем он) - тогда будет проще объяснить//"​.
 +
 +{{exploits-review-0x16_Image_3.png?​553}}
 +
 +Рисунок 4 описание ключа /SAFESEH линкера MS-LINK на MSDN
 +
 +А пока Харон спит (то есть, _теперь_ он конечно не спит, хотя… никаких гарантий на этот счет ни у кого нет), мы отправимся по ссылке,​ ведущей на Хароновский ftp-сервер:​ ftp://​ftp.styx.cabel.net/,​ где в директории pub лежит замечательный (и бесплатный — для некоммерческого использования линкер UniLink). Открываем файл whatsnew_ru.txt и втыкаем:​
 +
 +{{exploits-review-0x16_Image_4.png?​553}}
 +
 +Рисунок 5 в гостях у Юрия Харона,​ где на FTP-сервере лежит последняя версия линкера UniLink, обходящего многие ошибки Windows, с которыми другие линкеры не справляются
 +
 +-------------------------------------------------------------------------------
 +
 +build 3.13 [ulnb0313.zip]
 +
 ++ Добавлен ключ -RS для "​защиты"​ от инжекций SEH-обработчиков (этот механизм работает только в Vista и XPsp2), Поведение несколько отличается от ключа /SAFESEH ms-link (v8 или старше):​
 +
 +  - Отсутствие ключа - аналог /SAFESEH:NO
 +  - При указании ключа коллекционируется информация об обработчиках (аналог отсутствия ключа у ms-link), однако при отсутствии такой информации компоновка не отвергается (как у ms-link), а модуль маркируется как программа (dll) в которой запрещён SEH, При этом выдаётся информационное сообщение (из группы w-inf).
 +  - Строго в соответствии с документацией допустимы ссылки на "​внешние"​ обработчики (handler), в отличии от ms-link где такая ситуация приводит к ошибке. Это имеет значение при необходимости работы с "​нестандартными"​ обработчиками и/или с библиотеками в которых их назначение отсутствует. Ссылки на внешние обработчики,​ которые НЕ определены в компонуемом порождают '​Unresolved external';​
 +  - Для упрощения работы с библиотеками Borland (в которых нет информации об обработчиках) делается "​автоматическое"​ назначение обработчиков (они у Borland стандартные) - проверялось для C/CPP bc v5 и bcb v5/v6/bds4.
 +  - Указание ключа -RS+ приводит к запрету ИИ в отношении библиотек Borland.
 +Для остальных компиляторов можно использовать служебные файлы используядирективу .safeseh ml.
 +
 +-------------------------------------------------------------------------------
 +
 +Листинг 3 фрагмент файла whatsnew_ru.txt из комплекта поставки линкера UniLink
 +
 +Раскурив MSDN (отправные точки для поиска:​ http://​blogs.msdn.com/​greggm/​archive/​2004/​07/​22/​191544.aspx и http://​msdn2.microsoft.com/​en-us/​library/​9a89h429.aspx) можно узнать,​ что механизм SafeSEH, призванный предотвратить подмену обработчика структурных исключений при атаке на переполняющиеся буфера,​ в зачаточном виде появился еще в XP, но только в Висле он был доведен но минимально работающего состояния.
 +
 +{{exploits-review-0x16_Image_5.png?​553}}
 +
 +Рисунок 6 на блоге Microsoft, посвященному SafeSEH
 +
 +В чем его суть? Если раньше указатели на обработчики структурных исключений хранились в стеке, беспрепятственно доступном на запись/​чтение,​ то теперь они переместились в специальные секции PE-файла (см листинг 4),​ доступные только на чтение и формируемые статическим образом еще на этапе сборки программы при активном участии со стороны линкера и компилятора.
 +
 +extern PVOID __safe_se_handler_table[];​ /* base of safe handler entry table */
 +
 +extern BYTE  __safe_se_handler_count; ​ /* absolute symbol whose address is
 +
 + the count of table entries */
 +
 +typedef struct {
 +
 + ​DWORD ​ Size;
 +
 + ​DWORD ​ TimeDateStamp;​
 +
 + ​WORD ​ MajorVersion;​
 +
 + ​WORD ​ MinorVersion;​
 +
 + ​DWORD ​ GlobalFlagsClear;​
 +
 + ​DWORD ​ GlobalFlagsSet;​
 +
 + ​DWORD ​ CriticalSectionDefaultTimeout;​
 +
 + ​DWORD ​ DeCommitFreeBlockThreshold;​
 +
 + ​DWORD ​ DeCommitTotalFreeThreshold;​
 +
 + ​DWORD ​ LockPrefixTable; ​ // VA
 +
 + ​DWORD ​ MaximumAllocationSize;​
 +
 + ​DWORD ​ VirtualMemoryThreshold;​
 +
 + ​DWORD ​ ProcessHeapFlags;​
 +
 + ​DWORD ​ ProcessAffinityMask;​
 +
 + ​WORD ​ CSDVersion;
 +
 + ​WORD ​ Reserved1;
 +
 + ​DWORD ​ EditList; ​ // VA
 +
 + ​DWORD_PTR ​ *SecurityCookie;​
 +
 + ​PVOID ​ *SEHandlerTable;​
 +
 + ​DWORD ​ SEHandlerCount;​
 +
 +} IMAGE_LOAD_CONFIG_DIRECTORY32_2;​
 +
 +const IMAGE_LOAD_CONFIG_DIRECTORY32_2 _load_config_used = {
 +
 + ​sizeof(IMAGE_LOAD_CONFIG_DIRECTORY32_2),​
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + 0,
 +
 + &​__security_cookie,​
 +
 + ​__safe_se_handler_table,​
 +
 + ​(DWORD)(DWORD_PTR) &​__safe_se_handler_count
 +
 +};
 +
 +Листинг 4 новые структуры PE-файла,​ отвечающие за поддержку SafeSEH
 +
 +Утром Харон проснулся и отписал:​ "//​Ты про SafeSEH прочитал?​ Тогда рассказываю. Как оказалось (хоть они и врали что это только для висты) это _уже_ используется в XP SP2 (но не всех "​подбилдах"​!) для драйверов. А, поскольку,​ драйвера могут быть собраны как с этим ключом,​ так и без, то используется оно только в ситуации когда назначено. Практически,​ если посмотреть в процедуру RtlIsValidHandle,​ то увидим,​ что когда RtlLookupFuncionTable возвращает NULL (т. е. нет таблиц) хандлер считается валилдным (что правильно),​ при возврате INVALID_HANDLE_VALUE (возникает при IMAGE_DLLCHARACTERISTICS_NO_SEH) хандлер считается не валидным,​ а всё остальное рассматривается как описатель диапазона. Т.е. всё, вроде как, правильно.//​
 +
 +//​{{exploits-review-0x16_Image_6.png?​553}}//​
 +
 +Рисунок 7 функция NTDLL.DLL!RtlIsValidHandle под микроскопом дизассемблера IDA Pro
 +
 +//​Теперь смотрим в RtlLookupFunctionTable и видим что возвращаемое значение (точнее 2 значения) берутся из описания модуля в диапазон адресов которого попадает текущее исключение. Сиречь опять же все правильно. А вот теперь идём в то место где этот самый описатель модуля формируется (сиречь MiCaptureImageExceptionValues вызываемую из MmLoadSystemImage) и видим... подтверждение старого доброго правила — если обезьяне выдать пистолет,​ то ее обороноспособность понизится :)//
 +
 +//​Помнишь сколько было жалоб (в том числе и моих) на тему что MS некорректно обрабатывает — точнее говоря _не_ обрабатывает — (во многих местах) NumRvaAndSize в заголовке PE'​шника?​ Они решили исправиться. Но поручили это своим пионэрам :). И вот что получилось в результате (псевдокод)://​
 +
 +if(peh->​OptHdr.DllCharacteristics & ...NO_SEH)
 +
 +mdsc->​SEHtable = mdsc->​SEHcount = -1;
 +
 +else
 +
 +if(peh->​NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG)
 +
 +{
 +
 +if(peh->​DataDir[...] == NULL) mdsc->​SEHtable = mdsc->​SEHcount = 0;
 +
 +else
 +
 +{
 +
 +// init values
 +
 +}
 +
 +}
 +
 +Листинг 5 псевдокод,​ обрабатывающий поле NumRvaAndSize PE-заголовка
 +
 +//​Обращаем внимание,​ что при NumRvaAndSizes <= ...LOAD_CONFIG значения в таблице описания модуля остаются _неинициализированными_!//​
 +
 +//​Теперь вспоминаем,​ что память под эти описания (при загрузке драйверов) берётся динамически из nonpagedpool и возвращаемся в обработку исключений. Что происходит когда RtlLookupFunctionTable возвращает не 0 и не -1? Правильно,​ начинаем разбирать таблицу. Т. е. имеем (псевдокод) нечто вроде://​
 +
 +for(...)
 +
 +{
 +
 +...
 +
 +if(....
 +
 +&& cuFunction >= mdsc->​SEHtable[i]) return TRUE;
 +
 +}
 +
 +Листинг 6 псевдокод функции разбора таблицы исключений SEHtable
 +
 +//​…////​теперь вспоминаем что SEHtable у нас не инициализированный (сиречь содержит мусор) и получаем что? Правильно GPF. А теперь вспоминаем,​ что это место мы проходим при обработке ////​_////​любого////​_////​ исключения в драйвере (в том числе вполне штатного со своими обработчиками) в том числе и на IRQL > DISP и получим что? Правильно — BSOD. Например,​ при DebugPrint в ////release build ////и отсутствии отладчиков :)"//
 +
 +//​{{exploits-review-0x16_Image_7.png?​553}}//​
 +
 +Рисунок 8 BSOD возникающий из-за ошибки,​ допущенной разработчиками Windows, оставивших неинициализированные данные в таблицах,​ ответственных за поддержку SafeSEH
 +
 +