Срыв стека с передачей троянского кода
Рисунок 12.22. Срыв стека с передачей троянского кода
Даже если вредитель не может передать и исполнить код (например, потому, что не знает адреса стека или потому, что стек защищен от исполнения), порчи стекового кадра достаточно, чтобы аварийно завершить исполнение сетевого сервиса, а это тоже неприятно. Ошибки такого рода называются переполнениями буфера (buffer overrun) или срывами буфера. Если буфер находится в стеке, говорят еще о срыве стека. Срывы буфера возможны не только в сетевых сервисах, но и в приложениях, просто считывающих файлы и, с другой стороны, не только в высокоуровневых сетевых сервисах, но и в драйверах сетевых протоколов нижнего уровня -- последний тип ошибок особенно опасен, потому что атаке подвергается модуль ядра ОС. Особенную опасность представляет срыв буфера в модулях, осуществляющих парольную авторизацию: в этом случае злоумышленник может даже но разрушать стековый кадр, ему достаточно лишь модифицировать переменную, которая сигнализирует, что пароль успешно проверен.
Наиболее велика опасность срыва буфера в ситуациях, когда спецификация сетевого протокола или формата файла гласит, что длина того или иного поля или пакета не может превышать определенного количества байтов, однако нарушение этого правила физически возможно. Возможность такого нарушения может возникать как из-за того, что используется не счетчик байтов в пакете, а маркер конца пакета, так и из-за того, что разрядность счетчика байтов позволяет представлять значения, превышающие установленный протоколом предел.
Примечание
Обычно эти термины применяются для описания приемов, которые используются диверсантами для причинения ущерба системам", но важно понимать, что атаки такого типа основаны на ошибке в коде атакуемой системы. Если бы ошибки не было, диверсант не был бы в состоянии что-либо сделать (или, во всяком случае, был бы не в состоянии сделать именно это).
При программировании на языке С основные источники ошибок такого рода — это использование стандартных процедур gets и fscanf. Процедура gets лечению не подлежит — ей невозможно указать размер буфера, выделенного для приема данных, поэтому она в принципе не способна проконтролировать его заполнение. Вместо нее современные версии библиотек С предоставляют функцию fgets, которой размер буфера передается в качестве параметра. Настоятельно рекомендуется использовать именно ее.
Процедура fscanf в нашем случае лечится. Вместо
fscanf(socket, "%s %s\n", cmd, args);
нам следует написать
fscanf(socket, "%4s %255s\n", cmd, args);
Однако автоматизировать проверку того, что в каждом случае все форматные спецификаторы указаны правильно, невозможно, и поэтому использовать процедуру fscanf и другие процедуры того же семейства не рекомендуется.
Распространение червя Морриса через срыв буфера
Широко известен срыв буфера в программе fingerd, входившей в систему BSD Unix. На процессорах VAX и MC68000 отсутствует защита страниц памяти от исполнения, поэтому любая страница памяти, доступная для чтения, может быть исполнена.
"Червь Морриса" [КомпьютерПресс 1991] пользовался этой дырой, передавая кусок кода и поддельный стековый кадр, передававший управление этому коду. Код в свою очередь запускал на целевой системе копию командного интерпретатора, исполнявшуюся с привилегиями суперпользователя. Затем червь использовал полученный командный интерпретатор для втягивания в систему своего тела.
Ошибка была обнаружена в 1987 г. и вскоре после обнаружения была исправлена. Практически все современные системы используют безопасную в этом отношении версию fingerd. С тех пор сколько-нибудь серьезных (т. е. — вышедших за пределы одной группы взаимно доверяющих машин) атак червей на Unix-системы не происходило.
Червь Code Red, пандемия которого произошла в августе 2001 г., использовал срывы буфера в IIS (флагманский сетевой продукт Microsoft, сервер FTP/HTTP и ряда других протоколов для Windows NT/2000/XP). Как выяснилось, в данном случае речь шла не об одной, а о целой группе ошибок, потому что за выпуском patch, защищавшего от Code Red, последовало несколько других атак червей и поливалентных (т. е. использующих несколько каналов размножения) вирусов, часть из которых также привела к пандемиям. 19 сентября 2001 г. аналитическая компания Gartner Group выпустила доклад [www3.gartner.com 101034], в котором настоятельно рекомендовалось как можно скорее отказаться от использования IIS и высказывалась крайне пессимистическая оценка способности Microsoft исправить положение в обозримом будущем.
Срывы буфера являются одним из наиболее распространенных уязвимых мест: так, в базе данных [www.cert.orgl они составляют 27% от общего количества документированных проблем.
При использовании других языков программирования, например C++ с библиотекой классов для работы со строками, или Java, реализовать программу, подверженную срыву буфера, несколько сложнее, однако возможности человеческие неисчерпаемы, и многим программистам это удается. Впрочем, для программирующих на Java есть одно утешение: Java Virtual Machine использует более сложную схему управления памятью, чем компилируемые алголоподобные языки, и разрушить стековый кадр посредством переполнения буфера в программах, написанных на Java, невозможно, поэтому данный прием не может применяться для передачи и исполнения вредоносного кода. Однако неправильно обработанное исключение при ошибке индексации в буфере может привести к аварийной остановке приложения Java с ничуть не меньшим успехом, чем ошибка доступа к памяти в C/C++.
В тесном концептуальном родстве со срывами буфера находятся ошибки, срабатывающие при использовании во входном потоке данных недопустимых величин смещения (Рисунок 12.23). Такие ошибки встречаются при анализе входного потока, который содержит взаимосвязанные структуры данных, связи между которыми реализованы в виде смешений в потоке (я ссылаюсь на структуру данных, которая последует через 50 байт после этой точки). Практически важный пример такого протокола — система квитирования (посылки подтверждений) со скользящим окном, используемая в транспортном протоколе TCP [RFC 0793]. Адресация посредством смещений широко применяется также при работе с последовательными файлами, поэтому драйверы файловых систем и сетевые файловые серверы также могут содержать такие ошибки.