Атаки на кучу (она же динамическая память) приобретают все большую популярность, но методы переполнения, описанные в доступных хакерских руководствах, по ходу дела оказываются совершенно неработоспособными. Рассчитанные на древние системы, они не в курсе, что в новых версиях все изменилось. Более того, Free/Net/OpenBSD используют различные стратегии защиты кучи, особенности строения которой необходимо учитывать при написании эксплойтов. Мыщъх проделал титаническую работу, исследовав все версии популярных BSD-систем, и теперь не успокоится, пока не поделится добытой информацией с читателями.

 

Введение, или как все это начиналось

Сезон переполняющихся куч начался со статьи «Once upon a free()», опубликованной анонимусом в 39h номере phrack’а (8 января 2001 года), ссылающимся на более раннюю работу известного хакера Solar’а Designer’а (датируемую 25 июля 2000 года), в которой тот описал механизм передачи управления на shell-код, использующий особенности реализации макроса unlink в библиотеке glibc-2.2.3, поставляемой вместе с Linux. До этого хакерам было известно лишь стековое переполнение с подменой адреса возврата из функции. Переполнение кучи в общем случае приводило лишь к бездумному разрушению служебных структур динамической памяти и краху уязвимого приложения. Новый класс атак открывал радужные
перспективы непаханой целины, и обозначенная статья приобрела огромную популярность, породив кучу перепечаток в различных туториалах и езинах.

В конце июля 2002 года на Сеть обрушился червь Slapper, поражающий Linux-боксы и распространяющийся путем переполнения кучи через ошибку переполнения стека в OpenSSL. К BSD-системам такой механизм оказался неприменим в силу существенных конструктивных отличий строения кучи. Но уже 14 мая 2003 года хакер по кличке BBP рассказал, как атаковать аллокатор, разработанный фришным программистом по имени Poul-Henning Kamp, (далее по тексту phk-аллокатор). Когда phk-аллокатор стал использоваться в Free/Net/OpenBSD в качестве основного (теперь же он остался только в Net- и OpenBSD, причем в OpenBSD – в сильно переработанном виде), старые трюки
прекратили работать и молодые хакеры, начитавшиеся различных статей, сели на полный облом, завалив мыщъх’а грудами писем с вопросами: почему это не работает, как теперь жить и что делать? Вердикт: курить rtfm, конечно, полезно, но реальную пользу дают только свои собственные исследования, особенно в наш бурный век, когда опубликованные методы атаки теряют актуальность в течение нескольких месяцев. Так вот насчет исследований.

В конце 2005 года хакер под ником Phantasmal Phantasmagoria написал статью «The Malloc Maleficarum Glibc Malloc Exploitation Techniques», в которой предлагались новые механизмы атаки, пробивающие glibc версии 2.3.5 и выше. Статья остается актуальной по сей день, пусть и не без коррекции с учетом рандомизации адресного пространства, сторожевых страниц и других новомодных защитных технологий, появившихся в начале 2006 года.

В середине 2006 года Ben Hawkes выступил на конференции RexCon с презентацией «Exploiting OpenBSD», в которой показал, как атаковать кучу самой защищенной операционной системы всех времен и народов. Разработчики OpenBSD довольно оперативно отреагировали на ситуацию, выпустив обновленную версию аллокатора, затыкающую часть дыр. Разработчики Free- и NetBSD чешутся до сих пор, так что для хакерства складывается весьма благоприятная ситуация.

Мыщъх не предлагает готовых рецептов, но зато указывает на направление, двигаясь в котором можно подломать текущие и последующие версии аллокаторов не только в Free/Net/OpenBSD-системах, но и в Linux, ненавистной всем Висте и новоявленном Longhorn’е (он же Server 2008).

 

Обзор новых защитных технологий

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

 

Изменение структур данных

Heap smashed эксплойты вынуждены работать с низкоуровневыми структурами данных, поддерживающими жизнеобеспечение кучи, причем эти структуры не остаются постоянными, а меняются от версии к версии в целях не только защиты, но и элементарной оптимизации. Поэтому, чтобы заставить эксплойт работать, необходимо установить версию аллокатора, используемую жертвой, скачать исходные тексты (а в случае Windows засесть за дизассемблер) и соответствующим образом скорректировать код эксплойта. Если же версию аллокатора установить не удается (а удаленно ее установить очень сложно), следует поочередно перебирать все версии одну за другой.

 

Рандомизация адресного пространства

Эксплойты прежнего поколения закладывались на абсолютные адреса, по которым были расположены ключевые структуры данных, указатели и другая информация, пригодная для затирания. Теперь же затереть ее не так-то просто, поскольку операционные системы нового поколения активно используют рандомизацию адресного пространства (Address Space Layout Randomization, или сокращенно ASLR), меняя стартовые адреса библиотек и служебных структур динамической памяти случайным образом. OpenBSD и Виста используют рандомизацию кучи по умолчанию, в NetBSD она до сих пор не реализована, а разработчики FreeBSD в последних версиях отказались от ее использования в пользу производительности, так что реальную
угрозу для хакерства рандомизация представляет только на OpenBSD (рынок которой относительно невелик) и на Висте/Longhorn’е.

 

Сторожевые страницы

Для предотвращения переполнения блоки памяти, занимающие свыше 4 Кб, окружены сторожевыми страницами, попытка доступа к которым вызывает исключение. Однако блоки памяти меньше 4 Кб остаются незащищенными (в противном случае расходы памяти оказались бы просто немыслимыми), и к тому же внутри блоков память никак не защищена. То есть если мы имеем структуру вида struct X{char buf[0x10]; int *x; int *y}, то перезапись указателей x и y по-прежнему остается возможной! Сторожевые страницы в настоящий момент реализованы только в OpenBSD (смотри www.openbsd.org/papers/auug04/mgp00023.html), но даже в ней они
могут быть выключены для экономии памяти.

 

Контроль целостности кучи

Практически все современные аллокаторы в той или иной мере контролируют целостность служебных структур динамической памяти, предотвращая их затирание при переполнении, однако, зная алгоритм проверки, мы можем засунуть в затертые структуры подложные данные и… никто ничего не заметит! Как вариант — мы можем найти в куче указатель на блок памяти, передаваемый функции free(), и заменить его указателем на свой собственный блок, содержащий поддельную структуру данных.

 

Обфускация указателей

Для предотвращения чтения/записи указателей прибегают к их «шифровке» командой XOR. Указатели хранятся в памяти в зашифрованном виде и расшифровываются только перед непосредственным использованием, а потом шифруются вновь. В настоящий момент этот защитный механизм реализуют только Server 2008 и новые версии компилятора VC. Разработчики xBSD отказались от обфускации указателей ввиду чрезмерных накладных расходов, хотя OpenBSD позволяет включить обфускацию (по умолчанию она выключена).

 

История

Главная сложность атаки на кучу заключается в огромном количестве версий аллокаторов, каждая из которых требует индивидуального подхода, поэтому очень интересно было бы проследить этапы развития аллокаторов во Free/Net/OpenBSD-системах. Полный перечень изменений занял бы пару десятков страниц и был бы таким же скучным и труднопроходимым, как «Капитал» Маркса (часто используемый в качестве снотворного). К счастью, приводить его здесь нет необходимости, поскольку эта информация уже представлена в удобочитаемом виде на официальных сайтах BSD-систем. CVSWeb (web-интерфейс для CVS-хранилищ) просто незаменим, когда требуется изучить хронологию эволюции отдельного файла — в данном случае
malloc.c, который доступен по следующим адресам:

Мы же сосредоточимся только на «судьбоносных» изменениях, связанных с введением в строй новых защитных механизмов, а модернизацию служебных структур динамической памяти оставим за кадром.

 

FreeBSD

Ранние версии FreeBSD использовали простой и тормозной аллокатор, написанный в 1982 году программистом по имени Chris Kingsley и условно именуемый Caltech-аллокатором.

В сентябре 1995 года Caltech был заменен намного более продвинутым phk-аллокатором, который и стал основным для xBSD-систем на последующую пару десятков лет. Выпущенный под лицензией The beer-ware license (бесплатно, как пиво), он находит себе применение и по сей день.

Начиная с октября 1995 года, в phk-аллокаторе появились опции zero и junk, позволяющие диагностировать некоторые виды переполнения кучи. Впрочем, в то время кучу в xBSD-системах переполнять еще никто не собирался, и потому эти улучшения остались незамеченными.

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

Затем последовала череда многочисленных мелких изменений, за которой незаметно прошел 2001 год, отмеченный появлением эксплойтов под Linux, затем 2003 год, открывший эру атак на кучу xBSD. Закончился 2005 год, к концу которого хакеры справились с новыми версиями glibc, а разработчики FreeBSD все никак не реагировали на ситуацию и от атак не защищались, перекладывая эту заботу на плечи компилятора (учитывая, что большинство программ не использует кучу напрямую, а работает через glibc, позицию создателей FreeBSD можно понять).

Наконец, в январе 2006 года древний phk-аллокатор был отправлен на свалку истории и на его место пришел новый, улучшенный jasone-аллокатор, созданный программистом по имени Jason Evans. Функции malloc(), calloc(), posix_memalign(), realloc() и free() были полностью переписаны с учетом требований защиты и масштабируемости. Ну, последнее нас сейчас не волнует, так что сразу перейдем к защите: в jasone-аллокаторе появились сторожевые «красные зоны» (redzones), располагающиеся до и после всех блоков памяти, а также проверки на переполнение буферов, существенно затрудняющие атаку. Но… в марте 2006 года красные зоны были удалены по соображениям производительности, а в CVS-дереве
появился следующий комментарий: «Удалены красные зоны, поскольку переполнение буферов ничуть не более вероятно, чем разрушение внутренних структур динамической памяти», из чего надо полагать, что ни буферы, ни внутренние структуры не были защищены. Правда, в силу своей новизны jasone-аллокатор оказался достаточно стойким, и эксплойты, ориентированные на phk-аллокатор, с ним обломались, но! Базовые принципы атаки не изменились, и требовалась всего лишь адаптация эксплойтов под новые структуры данных. На момент написания этих строк FreeBSD продолжает использовать незащищенный jasone-аллокатор, представляющий собой легкую мишень для атаки.

 

NetBSD

Операционная система NetBSD, отбранченная от FreeBSD, во многом повторила ее путь. Сначала в ней использовался Caltech-аллокатор, но в июне 1999 года он был заменен phk-аллокатором, позаимствованным из FreeBSD. Изменения внутренних структур данных динамической памяти оказались несущественными, и потому обе системы оказались совместимыми с точки зрения эксплойтов.

Очередная серия изменений произошла в мае 2001 года, когда работники NetBSD перетащили новую версию phk-аллокатора из FreeBSD, слегка адаптировав ее в соответствии со своей философией и добавив ряд мелких проверок на переполнение кучи, которые, в общем-то, оказались совершенно несущественными с хакерской точки зрения.

В настоящий момент NetBSD продолжает использовать незащищенный phk-аллокатор. Рандомизация адресного пространства реализована только в стеке и секциях кода/данных, но куча остается нерандомизованной. Сторожевые страницы так же отсутствуют, как отсутствует обфускация указателей, а потому NetBSD легко атакуется древними эксплойтами. Впрочем, чтобы захватить управление, хакеру необходимо преодолеть защитный механизм PaX, интегрированный в NetBSD, подробнее о котором можно прочитать в моей статье «Переполнение буфера на системах с неисполняемым стеком» (смотри nezumi.org.ru/zq-nx.uncensored.zip), но это тема совсем
другого разговора, не имеющего к куче никакого отношения.

 

OpenBSD

Ох уж эта драконическая OpenBSD! Самая трудная мишень для атаки! Можно даже сказать, практически неприступная, но именно это и возбуждает хакеров, заставляя их искать весьма нетривиальные пути. Чтобы развеять миф о неприступности OpenBSD, достаточно вспомнить Ben’a Hawkes’а, атаковавшего кучу OpenBSD в 2006 году, то есть когда в ней уже были реализованы основные защитные механизмы, отсутствующие у конкурентов, но не будем забегать вперед и вернемся в далекий 1995 год, когда в OpenBSD использовался Caltech-аллокатор со всеми дырами, что в нем были.

В августе 1996 года разработчики OpenBSD позаимствовали phk-аллокатор из FreeBSD без каких бы то ни было существенных переделок, что позволило хакерам атаковать OpenBSD с той же легкостью, что и остальные системы.

В октябре 2003 года (то есть спустя полгода после открытия сезона атак на кучу хакером BBP) коллектив OpenBSD первым отреагировал на эту угрозу, выпустив усиленную версию phk-аллокатора, добавив в него сторожевые страницы и рандомизацию кучи. Это вызвало бурю восторга среди «трудящихся», которые вовсю использовали новый аллокатор на продакшн-машинах, считая себя абсолютно неуязвимыми.

Тем временем коллектив OpenBSD, вместо того чтобы почивать на лаврах, не отходил от клавиатур и ковал новое секретное оружие, которое было представлено народу в августе 2004 года. Появилась обфускация указателей, а рандомизация кучи была существенно усилена и теперь затрагивала не только адреса блоков памяти, но и местоположение служебных структур, что делало кучу полностью непредсказуемой и очень-очень сложно атакуемой. Однако в июне 2005 года по многочисленным просьбам «трудящихся» обфускация указателей была отправлена в отставку, поскольку оказалась чересчур тяжеловесной и негативно влияющей на производительность.

«Наш ответ Чемберлену» — вот девиз аллокатора, выпущенного в 2006 году и устраняющего ряд слабостей реализации, продемонстрированных на презентации Exploiting OpenBSD. Говоря техническим языком, для структур pginfo и pgfree был создан специальный аллокатор, который размещал их в отдельной области памяти (прежние версии аллокатора использовали для этих целей функцию imalloc). Чанки (chunks) переместились в специальный массив, размещаемый в случайном месте адресного пространства, в результате чего затереть служебные данные кучи в последних версиях OpenBSD практически невозможно, но создать подложный чанк и скормить его функции free() получится без проблем! Ведь обфускация указателей
по умолчанию отключена. Однако найти уязвимый указатель, пригодный для затирания, удается далеко не всегда, так что OpenBSD по праву носит звание самой защищенной операционной системы (только не надо путать «самую защищенную» с «защищенной вообще»).

 

Заключение

Вот мы и пробежались галопом по всем аллокаторам, которые только есть, рассмотрев их сильные и слабые стороны. И что же мы в итоге обнаружили? FreeBSD атаковать ничуть не сложнее чем NetBSD, однако из-за различных типов применяемых в них аллокаторов эксплойты получаются несовместимыми. OpenBSD – единственная система, существенно затрудняющая атаки на кучу, но… вовсе не делающая их принципиально невозможными!


Полную версию статьи
читай в декабрьском номере Хакера!

Оставить мнение

Check Also

Опубликована подробная информация о проблемах WPA2

Опубликованы подробности об уязвимостях в WPA2, представленных под общим названием KRACK. …