Атака форматной строки, в простейшем случае, такова:
char buffer[128];
gets(buffer);
printf(buffer);
Также существует уязвимость переполнения буфера, но суть в следующем: вы передаете ненадежные данные (от пользователя) в printf
(или одному из его двоюродных братьев), который использует этот аргумент в качестве строки формата.
То есть: если пользователь вводит "% s", вы получаете уязвимость раскрытия информации, потому что printf
будет обрабатывать ввод пользователя как строку формата и будет пытаться напечатать следующую вещь на стек как строка. Это как если бы твой код сказал printf("%s");
. Поскольку вы не передали никаких других аргументов printf
, он отобразит что-то произвольное.
Если пользователь вводит «% n», вы получаете потенциальную атаку с повышением привилегий (по крайней мере, атаку с отказом в обслуживании), поскольку строка формата% n заставляет printf
записать количество напечатанных символов до следующего места в стеке. Поскольку вы не дали ему место для установки этого значения, оно будет записано в произвольное место.
Это все плохо, и это одна из причин, почему вы должны быть чрезвычайно осторожны при использовании printf
и двоюродных братьев.
Что вы должны сделать, это:
printf("%s", buffer);
Это означает, что ввод пользователя никогда не обрабатывается как строка формата, поэтому вы защищены от этого конкретного вектора атаки.
В Visual C ++ вы можете использовать аннотацию __Format_string
, чтобы сказать ей, что нужно проверять аргументы printf
. %n
по умолчанию запрещено. В GCC вы можете использовать __attribute__(__printf__)
для того же самого.