19 смертных грехов, угрожающих безопасности программ - [12]

Шрифт
Интервал

В программах на языке C/C++ это особенно рискованно, поскольку обнаружить сомнительные места в форматной строке очень сложно, а кроме того, форматные строки в этих языках могут содержать некоторые опасные спецификаторы (и прежде всего %п), отсутствующие в других языках.

В C/C++ можно объявить функцию с переменным числом аргументов, указав в качестве последнего аргумента многоточие (…). Проблема в том, что при вызове такая функция не знает, сколько аргументов ей передано. К числу наиболее распространенных функций с переменным числом аргументов относятся функции семейства printf: printf, sprintf, snprintf, fprintf, vprintf и т. д. Та же проблема свойственна функциям для работы с широкими символами. Рассмотрим пример:

...

#include

int main(int argc, char* argv[])

{

if(argc > 1)

printf(argv[1]);

return 0;

}

Исключительно простая программа. Однако посмотрим, что может произойти. Программист ожидает, что пользователь введет что–то безобидное, например Hello World. В ответ будет напечатано то же самое: Hello World. Но давайте передадим программе в качестве аргумента строку %х %х. Если запустить эту программу в стандартном окне команд (cmd.exe) под Windows ХР, то получим:

...

E:\projects\19_sins\format_bug>format_bug.exe «%x %x»

12ffc0 4011e5

В другой операционной системе или при использовании другого интерпретатора команд для ввода точно такой строки в качестве аргумента может потребоваться слегка изменить синтаксис, и результат, вероятно, тоже будет отличаться. Для удобства можете поместить аргументы в shell–сценарий или пакетный файл.

Что произошло□ Функции printf передана форматная строка, вместе с которой следовало бы передать еще два аргумента, то есть поместить их в стек перед вызовом функции. Встретив спецификатор %х, printf прочтет четыре байта из стека. Нетрудно представить себе, что при наличии более сложной функции, которая хранит в стеке некоторую секретную информацию, противник смог бы эту информацию распечатать. В данном же случае на выходе мы видим адрес кадра стека (0xl2ffc0), за которым следует адрес, по которому вернет управление функция main(). То и другое – важная информация, которую противник сумел несанционированно получить.

Теперь возникает вопрос: «Как противник может воспользоваться ошибкой при работе с форматной строкой для записи в память□» Существует довольно редко используемый спецификатор %п, который позволяет записать число выведенных к настоящему моменту байтов в переменную, адрес которой передан в качестве соответствующего ему аргумента. Вот предполагаемый способ его применения:

...

unsigned int bytes;

printf("%s%n\n", argv[1], &bytes);

printf("Длина входных составляла %d символов\n, bytes");

В результате было бы напечатано:

...

E:\projects\19_sins\format_bug>format_bug2.exe «Some random input»

Some random input

Длина входных составляла 17 символов

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

Примечание. Более подробная демонстрация шагов, которые нужно предпринять для реализации такого эксплойта, приведена в главе 5 книги Michael Howard и David С. LeBlanc «Writing Secure Code, Second Edition» (Microsoft Press, 2002) или в книге Holesby Jack Koziol, David Litchfield, Dave Artel, Chris Anley, Sinan «noir» Eren, Neel Mehta and Riley Hassell «The Shellcoder\'s Handbook» (Справочник no shell–кодам) (Wiley, 2004).

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

В большинстве других языков эквивалент спецификатора формата %п не поддерживается, поэтому напрямую противник не сможет таким образом выполнить код по своему выбору. Тем не менее проблемы все равно остаются, поскольку существуют более тонкие варианты этой атаки, перед которыми уязвимы и другие языки. Если противник может задать форматную строку для вывода в файл протокола или в базу данных, то сумеет сформировать некорректный или сбивающий с толку протокол. Кроме того, приложение, читающее протоколы, может считать их заслуживающими доверия, а если это предположение нарушается, то ошибки в синтаксическом анализаторе могут все же привести к исполнению произвольного кода. С этим связана и другая проблема – запись в файл протокола управляющих символов. Так, символ забоя можно использовать для стирания данных, а символы конца строки могут скрыть или даже уничтожить следы атаки.


Рекомендуем почитать
Язык PL/SQL

В учебно-методическом пособии рассматриваются основы языка программирования PL/SQL, реализованного в системе управления базами данных Oracle Database Server. Приводятся сведения о поддерживаемых типах данных, структуре программ PL/SQL и выполнении SQL-предложений в них. Отдельно рассмотрено создание хранимых в базах данных Oracle программ PL/SQL – процедур, функций, пакетов и триггеров.


Пишем драйвер Windows на ассемблере

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


Язык программирования С# 2005 и платформа .NET 2.0.

В этой книге содержится описание базовых принципов функционирования платформы .NET, системы типов .NET и различных инструментальных средств разработки, используемых при создании приложений .NET. Представлены базовые возможности языка программирования C# 2005, включая новые синтаксические конструкции, появившиеся с выходом .NET 2.0, а также синтаксис и семантика языка CIL. В книге рассматривается формат сборок .NET, библиотеки базовых классов .NET. файловый ввод-вывод, возможности удаленного доступа, конструкция приложений Windows Forms, доступ к базам данных с помощью ADO.NET, создание Web-приложений ASP.NET и Web-служб XML.


Вариации на тему STL. Адаптер обобщенного указателя на функцию-член класса

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


Информационная технология. Руководство по управлению документированием программного обеспечения

ГОСУДАРСТВЕННЫЙ СТАНДАРТ РОССИЙСКОЙ ФЕДЕРАЦИИИнформационная технологияРУКОВОДСТВО ПО УПРАВЛЕНИЮ ДОКУМЕНТИРОВАНИЕМ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯInformation technology. Guidelines for the management of software documentationИздание официальноеДата введения 1994-07-01ГОССТАНДАРТ РОССИИ Москва© Издательство стандартов, 1994.


Самоучитель UML

Самоучитель UMLПервое издание.В книге рассматриваются основы UML – унифицированного языка моделирования для описания, визуализации и документирования объектно-ориентированных систем и бизнес-процессов в ходе разработки программных приложений. Подробно описываются базовые понятия UML, необходимые для построения объектно-ориентированной модели системы с использованием графической нотации. Изложение сопровождается примерами разработки отдельных диаграмм, которые необходимы для представления информационной модели системы.