Уязвимость форматной строки и предотвращение с примером

Опубликовано: 2 Марта, 2022

Строка формата - это строка ASCII, содержащая текст и параметры формата.

Пример:

// Оператор со строкой формата
printf ("меня зовут:% s  n", "Акаш");

// Выход
// Меня зовут: Акаш

Есть несколько строк формата, которые определяют вывод на C и многих других языках программирования, но мы сосредоточены на C.

Format string vulnerabilities are a class of bug that take advantage of an easily avoidable programmer error. If the programmer passes an attacker-controlled buffer as an argument to a printf (or any of the related functions, including sprintf, fprintf, etc), the attacker can perform writes to arbitrary memory addresses. The following program contains such an error:

// A simple C program with format
// string vulnerability
#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» и заставить printf думать, что это имеет 15 аргументов. Он наивно напечатает следующие 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

Примерно с 10 аргументами в стеке мы можем увидеть повторяющийся шаблон 0x252070 - это наши% ps в стеке! Мы начинаем нашу строку с AAAA, чтобы увидеть это более подробно:

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

0x41414141 - это шестнадцатеричное представление AAAA. Теперь у нас есть способ передать произвольное значение (в данном случае мы передаем 0x41414141) в качестве аргумента printf. На этом этапе мы воспользуемся еще одной функцией форматной строки: в спецификаторе формата мы также можем выбрать конкретный аргумент. Например, printf («% 2 $ x», 1, 2, 3) напечатает 2. Как правило, мы можем использовать printf («% $ x»), чтобы выбрать произвольный аргумент для printf. В нашем случае мы видим, что 0x41414141 является 10-м аргументом printf, поэтому мы можем упростить нашу строку1:

 $ ./a.out "AAAA% 10 $ p"
AAAA0x41414141

Предотвращение уязвимостей строки формата

  • Всегда указывайте строку формата как часть программы, а не как ввод. Большинство уязвимостей строки формата решаются путем указания «% s» в качестве строки формата, а не использования строки данных в качестве строки формата.
  • Если возможно, сделайте строку формата постоянной. Извлеките все переменные части как другие аргументы вызова. Трудно сделать с некоторыми библиотеками интернационализации
  • Если две вышеупомянутые практики невозможны, используйте средства защиты, такие как Format_Guard. Редко во время разработки. Возможно, это способ продолжить использовать устаревшее приложение и снизить расходы. Повысьте уверенность в безопасности стороннего приложения.

использованная литература
https://www.owasp.org/index.php/Format_string_attack
https://www.exploit-db.com/docs/28476.pdf

Эта статья предоставлена Акашем Шараном . Если вам нравится GeeksforGeeks, и вы хотели бы внести свой вклад, вы также можете написать статью с помощью provide.geeksforgeeks.org или отправить ее по электронной почте на deposit@geeksforgeeks.org. Посмотрите, как ваша статья появляется на главной странице GeeksforGeeks, и помогите другим гикам.

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

Хотите узнать о лучших видео и практических задачах, ознакомьтесь с Базовым курсом C для базового и продвинутого C.