Защита информации в Интернет

         

Взлом путем переполнения буфера



Взлом путем переполнения буфера

В ноябре 1996 года подходы к компьютерной безопасности изменились раз и навсегда. Ведущий списка рассылки Bugtraq Алеф Ван (Aleph One) опубликовал в номере 49 журнала Phrack Magazine, посвященного вопросам безопасности, статью под названием "Разрушение стека для развлечения и извлечения выгоды" (Smashing The Stack For Fun And Profit). Эта статья произвела колоссальный эффект на состояние дел в сфере обеспечения безопасности, поскольку в ней очень ясно показано, как практика некачественного программирования может привести к нарушению безопасности путем переполнения буфера. Первые упоминания об использовании этой методологии датируются 1988 годом в связи с нашумевшим делом о сетевом черве Роберта Морриса (Robert Morris), однако полезной информации о ее конкретных подробностях не было вплоть до 1996 года.
Состояние переполнения буфера (buffer overflow) возникает тогда, когда пользователь или процесс пытается поместить в буфер (или массив фиксированного размера) данных больше, чем для этого выделено памяти программистом. Подобная ситуация зачастую связана с использованием таких функций языка С, как strcpy (), strcat (} и sprintf (), а также ряда других. Переполнение буфера обычно приводит к генерации ошибки нарушения сегментации. Однако это состояние может вызываться преднамеренно с целью получения доступа к системе. Хотя мы рассматриваем методы взлома с помощью удаленного доступа, переполнение буфера может происходить и в локальных программах, о чем мы поговорим несколько позже. Для того чтобы лучше понять, как этот метод взлома срабатывает на практике, давайте рассмотрим один очень простой пример.
Допустим, для вводимых данных в программе выделяется буфер фиксированного размера 128 байт. Предположим, что этот буфер создается для размещения данных, поступающих от команды VRFY программы sendmail. Как вы помните из главы 3, эта команда использовалась для того, чтобы установить потенциальных пользователей по их почтовым адресам. Предположим также, что sendmail запущена в контексте прав SU1D пользователя root и пользуется его привилегиями (во многих системах этот так и есть, хотя и не всегда). Что произойдет, если взломщик подключится к демону sendmail и отправит в качестве параметра команды VRFY строку состоящую из 1000 символов а, а не короткое имя пользователя?
echo "vrfy 'perl -е 'print "a" x 1000''" |nс www.targetsystem.com 25
Поскольку буфер, предназначенный для хранения параметра VRFY, имеет размер всего 128 байт, возникнет ситуация его переполнения. Это может привести к генерации состояния DoS и аварийному завершению демона sendmail. Однако более опасными являются ситуации, когда программа, буфер которой переполнился, продолжает работать и выполняет при этом программный код, переданный ей в виде избыточных данных. Именно это и является основным смыслом рассматриваемой в данном разделе атаки.
Вместо того, чтобы отправлять бессмысленную строку, состоящую из 1000 символов а, взломщик, скорее, передаст определенный набор кодов, который после переполнения буфера выполнит команду /bin/sh. Если, как мы условились, sendmail работает с привилегиями суперпользователя, то после запуска /bin/sh взломщик сразу же сможет получить доступ в качестве суперпользователя. Возможно, вы никак не можете понять, каким же образом программа sendmail узнает, что ей нужно выполнить команду /bin/sh? Все очень просто. В процессе взлома в качестве параметра команде VRFY передается строка, содержащая некоторый ассемблерный код, призванный вызвать переполнение буфера. При переполнении буфера адрес возврата переустанавливается на код, переданный хакером, что позволяет последнему получить полный контроль над программой. Иными словами, вместо возврата управления из функции по нужному адресу выполняется некоторый код взломщика, передаваемый в этом же пакете данных и запускающий команду /bin/sh.
Конечно, необходимо помнить, что ассемблерный код очень сильно зависит от архитектуры и используемой операционной системы. Поэтому данные, используемые для переполнения буфера системы Solaris, установленной на компьютерах с процессорами Intel, не имеют ничего общего с данными, предназначенных для взлома системы Solaris компьютеров SPARC. Следующий пример показывает, как выглядит машинный код (такой код еще называют "яйцом" (egg), по аналогии с яйцами кукушки, которые она подкладывает в чужие гнезда), предназначенный переполнения буфера на платформе Linux X86.

char shellcode[]= "\xeb\xlf\x5e\x89\x76\x08\x31\xcO\
x88\x46\x07\x89\x46\xOc\xbO\xOb"
"\x89\xf3\x8d\x4e\x08\x8d\x56\xOc\xcd\
x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";

Очевидно, что взлом с помощью переполнения буфера чрезвычайно опасен. Достаточно сказать, что он не раз использовался во многих успешных попытках получения несанкционированного доступа. Приведенный выше пример очень прост. На самом деле работающий код создать очень трудно. Однако зачастую изобретать велосипед не приходится: множество таких "яиц" уже было создано хакерами и помещено в Internet. Описание деталей процесса создания "яйца" выходит за рамки этой книги, поэтому мы советуем познакомиться с упоминавшейся выше статьей хакера Алефа Вана в журнале Phrack Magazine. Если вы хотите улучшить свои навыки написания ассемблерного кода, прочтите книгу Криса Дрейка (Chris Drake) и Кимберли Браун (Kimberley Brown) Panic — UNIX System Crash and Dump Analysis. Кроме того, группа программистов и специалистов по безопасности Тесо (Teso) разработала несколько утилит, которые позволяют автоматически генерировать подобный код. Эти средства можно найти по адресу http://teso.scene.at/releases.php.

Содержание раздела