The YapLink Project The YapLink Project The YapLink Project The YapLink Project The YapLink Project The YapLink Project The YapLink Project The YapLink Project The YapLink Project The YapLink Project The YapLink Project The YapLink Project The YapLink Project The YapLink Project The YapLink Project

Уязвимость форматирующей строки

Tartuga

Местный
Регистрация
19.12.2019
Сообщения
101
Реакции
22
Ошибка форматирования строки стала известна еще в далеком 1989 году при работе по fuzz testing в Университете Висконсина. Но только лишь спустя 10 лет в 1999 году было обнаружено использование данной уязвимости в качестве вектора атака в ходе конференции по безопасности ProFTPD-демона Вашингтонского университета. Это привело к первой публикации данной уязвимости в сентябре 1999 года в списке Bugtraq. Но по настоящему массово данная уязвимость стала эксплуатироваться лишь в 2000 году. Было написано множество эксплоитов на базе форматирования строки. Ошибки обнаруживались как в больших популярных серверных приложениях, так и в простых утилитах.



*(Все примеры далее буду приводить на С)

Итак, форматирующая строка - простое представление строки ASCII контролируемым образом с использованием спецификаторов формата. Чтобы преобразовать типы данных в строке в представление String, используются такие функции, как printf , vprintf , scanf. Уязвимость форматирующих строк появляется несколькими способами. Вызов * printf () без спецификатора формата является опасным и может быть использован. Например, printf (input) можно использовать. Результат данного вызова позволяет злоумышленнику заглянуть в стек, тк входная строка будет использоваться в качестве спецификатора формата. Злоумышленник может заполнить входную строку спецификаторами формата и начать считывать значения стека, поскольку остальные параметры будут удалены из стека. В худшем случае эта уязвимость позволит злоумышленнику записать произвольное значение в память запущенной программы.



Проведение атаки:

Выводимое функцией количество символов будет храниться в адресе аргумента, следующего за самой строкой формата. Но в коде, имеющем уязвимость, злоумышленник может предоставить только одну строку (опустив второй аргумент функции printf). Функция printf возьмет очередное значение в стеке и использует его в качестве второго аргумента. Взломщик может также заставить функцию printf воспользоваться следующим значением в стеке, предоставив в качестве ввода, к примеру, такую форматирующую строку: %08x

Это означает, что printf выведет следующий аргумент в виде 8-разрядного шестнадцатеричного числа.

Рассмотрим далее на примере данного кода:

#include<stdio.h>

int main(int argc, char** argv)
{
char buffer[100];
strncpy(buffer, argv[1], 100);

// We are passing command line
// argument to printf
printf(buffer);

return 0;
}



ТК printf имеет использует строку формата для определения количества аргументов, то злоумышленник может передать строку: %p%p%p%p%p%p%p%p%p%p%p%p%p%p%p

%p - внешнее представление указателя на недействительность printf будет печатать следующие 15 адресов в стеке, думая, что они являются его аргументами
Вот что получится:

$ ./a.out "%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p"
0xffffdddd 0x64 0xf7ec1289 0xffffdbdf 0xffffdbde (nil) 0xffffdcc4 0xffffdc64 (nil) 0x25207025 0x70252070 0x20702520 0x25207025 0x70252070 0x20702520

C 10 аргумента идет чередование - это введенные наши %p в стеке. Теперь мы можем передать наше значение. Передадим наше значение, добавив AAAA

$ ./a.out "AAAA%p%p%p%p%p%p%p%p%p%p%p"
AAAA0xffffdde8 0x64 0xf7ec1289 0xffffdbef 0xffffdbee (nil) 0xffffdcd4 0xffffdc74 (nil) 0x41414141

Итак, мы передали 0x41414141 - 16-ю запись AAAA



Безопасность:

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