Чтение онлайн

ЖАНРЫ

Защита от хакеров корпоративных сетей

авторов Коллектив

Шрифт:

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

выведено содержимое области памяти, адрес начала которой указан злоумышленником, а адрес конца определяется по первому нулевому байту, встретившемуся при выводе.

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

Запись в память

В предыдущих разделах уже затрагивалась спецификация формата %n. Эта некогда малопонятная спецификация позволяет определить текущий размер формируемой строки. Значением переменной, соответствующей спецификации преобразования %n, является адрес памяти. Если во время выполнения функции printf в форматирующей строке встречается спецификация преобразования %n, то в память по адресу, указанному этой переменной, записывается количество символов сформированной строки в формате целого числа.

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

Способ однократной записи. Обсуждаемый способ позволяет увеличить права доступа, используя форматирующую строку с единственной спецификацией преобразования %n.

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

Утилита Screen является примером программы, которая может быть атакована таким образом. Эта популярная утилита в системе UNIX позволяет многочисленным процессам использовать один и тот же псевдотерминал. При установленных правах суперпользователя утилита сохраняет права доступа вызвавшего ее пользователя в памяти. При создании окна родительский процесс утилиты Screen понижает права доступа процессов потомков до значения прав, сохраненных в памяти, например до уровня прав оболочки пользовательского интерфейса и т. д.

В версиях утилиты Screen до 3.9.5 включительно содержится уязвимость форматирующей строки, которая проявляется при выводе строки визуализации звукового сигнала (visual bell). Эта строка определяется данными файла конфигурации пользователя с расширением . screenrc. Строка визуализации звукового сигнала выводится на терминал пользователя и интерпретирует символ звукового сигнала в кодировке ASCII. При выводе на терминал определяемые пользователем данные из конфигурационного файла передаются функции printf как часть форматирующей строки – первого параметра функции.

Благодаря алгоритму работы утилиты Screen злоумышленник может воспользоваться обсуждаемой уязвимостью форматирующей строки при помощи способа однократной записи по спецификации преобразования %n. Для атаки ему не потребуется ни управляющего кода, ни задания адресов памяти. В основе идеи использования уязвимости форматирующей строки лежит подмена сохраненного идентификатора пользователя userid на другой, выбранный злоумышленником, например 0 – идентификатор суперпользователя.

Для того чтобы воспользоваться уязвимостью форматирующей строки, злоумышленник должен сделать следующее. Во-первых, присвоить одному из параметров небезопасной функции printf адрес области сохранения идентификатора пользователя в памяти. Во-вторых, создать форматирующую строку со спецификацией преобразования %n, которая соответствует параметру, передающему

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

На локальной машине злоумышленник, воспользовавшись уязвимостью форматирующей строки в утилите Screen, может повысить свои права доступа до уровня прав суперпользователя. Рассмотренная уязвимость утилиты Screen является хорошим примером использования злоумышленниками ошибок форматирующей строки для тривиального осуществления своих замыслов. Описанный способ применим для большинства известных платформ.

Способ многократной записи. Этот способ заключается в перезаписи сразу нескольких участков памяти. Он сложнее метода однократной записи, но зато дает лучшие результаты. Используя уязвимость форматирующей строки, злоумышленник часто имеет возможность заменить почти любое значение в памяти на значение, нужное ему. Для понимания способа многократной записи важно знать, как работает спецификация преобразования %n и что происходит во время записи.

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

Принципы работы программ атаки, использующих ошибки форматирующих строк

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

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

Обычно злоумышленнику доступен более простой способ определения искомой позиции в стеке. В большинстве уязвимых программ форматирующая строка, передаваемая функции printf, сама хранится в стеке как локальная переменная. Из-за того, что обычно в стеке хранится не так много локальных переменных, форматирующая строка расположена недалеко от стекового фрейма вызванной уязвимой функции printf. Злоумышленник может воспользоваться уязвимой функцией для записи данных в нужные ему адреса памяти, если он включит их в список параметров функции printf, а в форматирующей строке разместит в нужные позиции спецификации преобразования %n.

Поделиться с друзьями: