Личный блог Suvan`a.

Работая и играя с Linux... И что из этого иногда получается.

Защита памяти: StackGuard.

Рубрика: Безопасность -> Укрепляем Linux
Метки:
Четверг, 28 мая 2009 г.
Просмотров: 4884

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

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


     StackGuard.

     StackGuard был разработан в 1998 г. как часть дистрибутива Immunix, но в то же время его надо было загружать отдельно. Во время его написания последней версией GCC была версия 2.96. В июне 2003 г. было объявлено, что новая версия StackGuard будет написана на GCC 3.x, но до сих пор данного не произошло. Поэтому не будем описывать инсталляцию и использование StackGuard, но потолкуем о том, как он работает, так как подобным образом работают несколько аналогичных проектов.

     Ранее было показано, как хакер заставляет процессор реализовывать свой код. Он помещает инструкции в буфер и вызывает переполнение бу­фера. Адрес RET (адрес возврата) перезаписывается и устанавливается на начало буфера. В результате данного процессор начинает исполнять инструк­ции хакера. StackGuard помещает в стек специальное значение (canary value) непосредственно после RET, как показано на рисунке.

StackGuard

     Это значение проверяется сразу после возврата функции. Любая попыт­ка изменения адреса возврата (RET) приводит к изменению данного значения. StackGuard дает эффективный способ определения изменения значения RET

     Конечно, хакер может перезаписать и это значение, подкоррек­тировав его конкретным образом, чтобы StackGuard не заметил этого.

     Но разработчики StackGuard предусмотрели и такой вариант развития со­бытий: употребление произвольных значений и использования терминатора значений. В некоторых версиях StackGuard были доступными оба метода, но в последних версиях применяется только последний - терминатор.

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

Однако хакер может получить доступ к части системной памяти, содержащей это значение, и завладеть им. Правда, такой сценарий возможен, только если хакер получил права root. Но зачем тогда ему все это, если его цель (права root) достигнута.

     Если знаете язык С, то должны знать, что символ \0 применяется для внутреннего представления конца строки. Создатели эксплоитов должны убедиться, что их shell-код не содержит данного символа, в противном случае выполнение кода будет преждевременно прервано. Терминаторы исполь­зуют как раз эту технику: они заполняют проверочное значение четырьмя разными терминаторами строки: \0 (NULL), CR, LF и -1.

Если хакер хочет перезаписать RET, его shell-код должен повторно запол­нить проверочное значение этими терминаторами. Так как он пытается переполнить массив символов, эти терминаторы будут обработаны как конец строки и оставшийся shell-код просто будет проигнорирован.

     Режим защиты MemGuard.

     StackGuard тоже дает еще один режим защиты - MemGuard. Вместо использования проверочных значений MemGuard просто помечает страницу памяти как read-only, это означает, что страница будет доступна только для чтения, и потом устанавливает собственный обработчик.

     Этот обработчик перехватывает все попытки записи в эту область памя­ти и эмулирует запись, если она направлена на некритическую часть стра­ницы (то есть не на адрес возврата). Такая техника более безопасна, но запись в память происходит в 1800 раз медленнее, что делает употребление MemGuard бесполезным.