Эксплойтный ликбез Олег Толстых aka NSD Xakep, номер #066, стр. 066-070-2 int format_bug(char *str) { int k = 9; printf(str); return 0; } Эта функция должна выводить в stdout содержимое передаваемой через параметры переменной str. Если передать функции строку «Hi, people!», на экран выведется то же самое, что и вводилось. Какая же ошибка может быть тут? Попробуем передать функции строку «%x_%x_%x_%x_%x_%x_Hi, ppl!». Что же мы видим? Вместо ожидаемого результата на экране появилась строка “9_fff6_2fc_ff92_7825_255f_Hi, ppl!”. Из-за чего могло такое произойти? Фишка в том, что printf() обрабатывает входные данные, воспринимая некоторые символы как форматные спецификаторы, и как ты уже понял, 9_fff6_2fc_ff92_7825_255f является соответствием %x_%x_%x_%x_%x_%x. Шестнадцатеричные представления чисел, которые ты видишь выше, это не что иное, как данные из стека. Число 9 – это значение переменной k, fff6 – сохраненное в стеке содержимое регистра bp, 2fc – адрес возврата функции format_bug и т.д. Таким образом можно вывести содержимое всего стека. А ведь в нем могут находиться пароли, приватные ключи для шифрования и прочая важная инфа! Используя хитрым образом форматный преобразователь «%n», хакер может даже перезаписывать нужную область стека. Главное, он может перезаписать адрес возврата функции. К чему это приводит - я писал выше. Ошибка программиста заключается в том, что он не указал printf’у тип выводимых данных, в результате чего пользователь смог сам влиять на строку форматных спецификаторов. Если бы в коде вместо строки «printf(str);» он написал «printf(“%s”,str);», все работало бы без багов. Собственно говоря, эти две уязвимости чаще всего используются хакерами при написании эксплойтов. Компиляция *nix’овых эксплойтов Обычно эксплойты пишут под одну из двух популярных платформ - под форточки от всеми любимых мелкомягких или под никсы. Для того чтобы откомпилить никсовый сплойт, вовсе не обязательно ставить себе unix. Обычно хакеры взламывают какой-нибудь сервак и используют его как плацдарм для хака, собирая и запуская remote-сплойты прямо на нем. Чтобы собрать *nix-exploit, следует заюзать компилятор gcc, который имеется на большинстве серверов. Компилируется эксплойт следующим образом. В командной строке оболочки оси набирается команда gcc expl.c –o expl. В нашем случае, expl.c – имя файла исходника, expl – имя конечного файла. Если процесс компиляции завершится успешно, в той же папке, в которой находятся сорцы сплойта (expl.c), появится новый файл-бинарник expl, который как раз и можно запускать. Удаленные сплойты можно компилить где угодно, а вот локальные лучше всего собирать прямо на машине-жертве. Хотя часто бывает так, что шелл на сервере есть, но доступ к компилятору ограничен. В этом случае лучшее решение – собрать сплойт на другой машине, работающей под аналогичной операционной системой, при этом нужно понимать, что если ты соберешь сплойт под OpenBSD 3.4, он не будет работать во FreeBSD 4.9. |