C: чтение большего количества байтов, чем форматная строка, с помощью инъекции форматной строки
В работе , использующей уязвимости форматных строк, авторы приводят следующий пример кода, где input
- это некоторый нефильтрованный пользовательский ввод.
char outbuf[512];
char buffer[512];
sprintf (buffer, "ERR Wrong command: %400s", input);
sprintf (outbuf, buffer);
Затем они объясняют, что, используя специальную строку формата в качестве входных данных, они могут обойти ограничение %400s
:
"%497dx3cxd3xffxbf<nops><shellcode>"
Это создает строку длиной 479 символов. Однако я не могу найти объяснения тому, как %479d
обходит ограничение %400s
. Как этот вход позволяет sprintf записать строку, которая является длиннее 400 символов?
2 ответа:
Второй
sprintf()
переполняетoutbuf
, потому что он использует строку формата, сгенерированную первымsprintf()
, и размещение "%497d" в этой строке заставляет его печатать 497-char широкое целочисленное поле (дополненное пробелами, чтобы получить полную ширину). Это вместе с остальной частью этой строки превысит размер буфера 512-charoutbuf
. Это также заставит его попытаться прочитать целочисленный аргумент, который на самом деле не передается функции (2ndsprintf()
).
Проблема заключается в том, что если
input
содержит маркеры%
, тоbuffer
будет содержать эти маркеры%
(после первогоsprintf()
), а затем, используя второйsprintf()
, "строка формата" будетbuffer
и маркеры%
в ней будут интерпретированы, даже если нет аргументов для интерполяции вoutbuf
. Чтобы избежать этой проблемы:snprintf(outbuf, sizeof(outbuf), "%s", buffer);
Или
strcpy(outbuf, buffer);
В этом контексте
snprintf()
является излишним, но он обнажает механизм до основ.