C: Чтение большего количества байтов, чем строка формата, с внедрением строки формата

В документе Использование уязвимостей форматной строки авторы приводят следующий пример кода, в котором input — это нефильтрованный пользовательский ввод.

char outbuf[512];
char buffer[512];
sprintf (buffer, "ERR Wrong command: %400s", input);
sprintf (outbuf, buffer);

Затем они объясняют, что, используя специальную строку формата в качестве входных данных, они могут обойти ограничение %400s:

"%497d\x3c\xd3\xff\xbf<nops><shellcode>"

Это создает строку длиной 479 символов. Однако я не могу найти объяснение тому, как %479d обходит ограничение %400s. Как этот ввод позволяет sprintf записывать строку длиннее 400 символов?


person Community    schedule 03.12.2014    source источник


Ответы (2)


Второй sprintf() переполняет outbuf, потому что он использует строку формата, сгенерированную первым sprintf(), и размещение "%497d" в этой строке заставляет его печатать целочисленное поле шириной 497 символов (дополненное пробелами, чтобы получить полную ширину). Это вместе с остальной частью этой строки превысит размер буфера outbuf из 512 символов. Это также заставит его попытаться прочитать целочисленный аргумент, который на самом деле не передан функции (2nd sprintf()).

person Dmitri    schedule 03.12.2014

Проблема в том, что если input содержит % маркеров, то buffer будет содержать эти % маркеры (после первого sprintf()), а затем, используя второй sprintf(), «строка формата» будет buffer, а % маркеры в ней будут интерпретированы, хотя нет аргументов для интерполяции в outbuf. Чтобы избежать проблемы:

snprintf(outbuf, sizeof(outbuf), "%s", buffer);

or

strcpy(outbuf, buffer);

В этом контексте snprintf() является излишним, но он сводит механизм к основам.

person Jonathan Leffler    schedule 03.12.2014