Информационная безопасность



              

Неизвестная уязвимость функции printf - часть 4


Это происходит в тех случаях, когда пропущенная переменная оказывается на верхушке стека, что не так уж и маловероятно. Но ошибка может неожиданно проявится при переходе на другой компилятор, поскольку порядок расположения локальных переменных нигде не задекларирован, и каждый компилятор группирует их по-своему (вовсе не факт, что переменные всегда располагаются в памяти в порядке их объявления в программе).

В тех случаях, когда функция printf используется для вывода единственной символьной строки, строку спецификаторов обычно опускают, т.е. вместо “printf (“%s”, &buff[0])” пишут “printf(&buff[0])”. На первый взгляд обе формы записи равносильны, но это не так! Самый левый аргумент всегда проверяется функцией printf на наличие спецификаторов, даже если он передан функции в единственном числе. Поэтому использовать его для вывода строки можно в том и только том случае, когда она гарантированно не содержит никаких "внеплановых" спецификаторов, в противном случае, работа приложения окажется нестабильной. Особенно опасно полагаться на отсутствие спецификаторов в данных, введенных пользователем, и недопустимо передавать их функции printf в первом слева аргументе.

Возможные последствия такого подхода позволяет продемонстрировать программа, приведенная в начале статьи: если злоумышленник введет вместо пароля один или несколько спецификаторов, на экране появится содержимое локальных переменных, в том числе и буфера, хранящего эталонный пароль. Компилятор Microsoft Visual C++ 6.0 располагает этот буфер на вершине стека и просмотреть его можно следующим образом (предполагается, что файл “buff.psw” содержит строку “K98PN*”):

printf bug demo Login:kpnc Passw:%x %x %x Invalid password: 5038394b a2a4e 2f4968

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

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


Содержание  Назад  Вперед