Отметим, что хотя при вызове функции printf
не был задан параметр функции, соответствующий спецификации вывода целого числа со знаком %i , тем не менее в формируемую строку было включено целое число. Функция прочитала из области стека, в которую был бы помещен незаданный параметр функции, какие-то данные и представила их в формате целого числа со знаком. В данном случае после представления найденных байтов в формате целого десятичного числа со знаком получилось число -1073742952. Таким образом, если дополнить форматирующую строку своими спецификациями формата, то можно воспользоваться функцией printf
для просмотра содержимого стека, потому что функция printf выведет содержимое областей стека в соответствии с заданными спецификациями формата.Как будет показано дальше, возможность управления функцией printf
через входные данные программы может привести к образованию серьезной бреши в защите. При наличии программы с ошибками форматирующей строки, которая для формирования выводимой строки использует входные данные программы, злоумышленник сможет прочитать содержимое критических участков памяти. Такие участки памяти могут быть перезаписаны с использованием форматирующей строки с малопонятной спецификацией формата %n. Спецификация преобразования %n, известная также как указатель на целое, позволяет получить текущее число символов форматируемой строки в момент обработки указателя на целое. Как злоумышленник сможет воспользоваться ошибками форматирующих строк, будет объяснено далее во время изучения программы атаки, использующей ошибки форматирующей строки.Как и почему возникают ошибки форматирующей строки?
Основная причина возникновения ошибок форматирующей строки заключается в использовании программистом непроверенных входных данных в форматирующей строке. Ниже приведены наиболее известные ошибки программирования, обусловленные уязвимостью форматирующей строки.
Первая ошибка состоит в том, что при вызове функции printf ей передается единственная непроверенная строка. Например:printf(argv[1]);
При этом единственная передаваемая переменная (часто передается первый аргумент командной строки) расценивается функцией как форматирующая строка. И если в эту переменную будут включены спецификации преобразования, то функция среагирует на них.
[dma@victim]$ ./format_example %i -1073742936
Часто эта ошибка совершается начинающими программистами из-за плохого знания особенностей функций обработки строк. Но порой эта ошибка является следствием лени программиста, не удосужившегося задать форматирующую строку (то есть дополнительно написать спецификацию вывода строки %s). Обычно именно это становится основной причиной появления брешей в системе безопасности программ. Очень часто программисты пользуются функциями записи сообщений в системный журнал и выдачи сообщений об ошибке. При использовании функции выдачи сообщения об ошибке программисты-разработчики нередко забывают о том, что она вызывает внутри себя функцию printf
(или любую другую из семейства функций printf) и передает ей переменное число аргументов. Может быть, они привыкли вызывать ее для печати единственной строки:error warn(errmsg);