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()является излишним, но он обнажает механизм до основ.