Выбрать главу

/* sprbufo.c */

/* Hal Flynn <mrhal@mrhal.com> */

/* December 31, 2001 */

/* sprbufo.c demonstrates the problem */

/* with the sprintf() function which */

/* is part of the c library. This */

/* program demonstrates sprintf not */

/* sufficiently checking input. When */

/* executed with an argument of 8 bytes */

/* or more a buffer overflow occurs. */

#include <stdio.h>

int main(int argc, char *argv[])

{

overflow_function(*++argv);

return (0);

}

void overflow_function(char *b)

{

char c[8];

sprintf(c, “%s”, b);

return;

}

Как и в предыдущем примере, строка символов аргумента программы копируется в восьмибайтовый массив символов. Поскольку при копировании из argv [1] не выполняется никаких проверок на соответствие размера пересылаемых данных размеру памяти, в которую выполняется копирование, то в результате возможно переполнение буфера. Применение функции strcat без проверки размера обрабатываемых данных также может привести к переполнению буфера, как это видно из следующего примера:

/* scatbufo.c */

/* Hal Flynn <mrhal@mrhal.com> */

/* December 31, 2001 */

/* scatbufo.c demonstrates the problem */

/* with the strcat() function which */

/* is part of the c library. This */

/* program demonstrates strcat not */

/* sufficiently checking input. When */

/* executed with a 7 byte argument, a */

/* buffer overflow occurs. */

#include <stdio.h>

#include <strings.h>

int main(int argc, char *argv[])

{

overflow_function(*++argv);

return (0);

}

void overflow_function(char *b)

{

char c[8] = «0»;

strcat(c, b);

return;

}

Данные командной строки из массива argv [1] передаются функции overflow_function, которая сцепляет их с данными восьмибайтового массива символов с. Поскольку в программе размер сцепляемых данных не проверяется, то в результате возможен выход за границы массива c. Gets – еще одна проблематичная функция языка C. Компилятор GNU языка C выдает предупреждающее сообщение при компиляции программ с функцией gets, потому что эта функция никак не контролирует размер получаемых данных. Посмотрите на следующий пример:

/* getsbufo.c */

/* Hal Flynn <mrhal@mrhal.com> */

/* December 31, 2001 */

/* This program demonstrates how NOT */

/* to use the gets() function. gets() */

/* does not sufficient check input */

/* length, and can result in serious */

/* problems such as buffer overflows. */

#include <stdio.h>

int main()

{

get_input();

return (0);

}

void get_input(void)

{

char c[8];

printf(“Enter a string greater than seven bytes: ”);

gets(c);

return;

}

В исходном тексте программы можно найти функцию gets. В результате выполнения функции gets данные входного потока пересылаются в восьмибайтовый массив символов c. Но поскольку эта функция не выполняет никаких проверок на размер обрабатываемых данных, то в результате легко получить ошибку переполнения буфера.

Подробнее с проблемой переполнения буфера можно познакомиться в главе 8.

Ошибки проверки входных данных

Причина других типичных ошибок программирования кроется в недостаточной проверке входных данных программы. В результате уязвимость программы может проявиться при передаче ей различных типов данных, как, например, это происходит с программами Web CGI.

Ошибки проверки входных данных программы могут привести к уязвимостям форматирующей строки. Уязвимость форматирующей строки проявляется при использовании в программе таких спецификаций преобразования, как, например, %i%i%i%i или %n%n%n%, что может привести к неожиданному результату. Подробно форматирующие строки рассмотрены в главе 9.

Но перед этим приведем пример программы с уязвимой форматирующей строкой. Проанализируйте следующую программу:

/* fmtstr.c */

/* Hal Flynn <mrhal@mrhal.com> */

/* December 31, 2001 */

/* fmtstr.c demonstrates a format */

/* string vulnerability. By supplying */

/* format specifiers as arguments, */

/* attackers may read or write to */

/* memory. */

#include <stdio.h>

int main(int argc, char *argv[])

{

printf(*++argv);

return (0);

}

В результате запуска программы и передачи ей на вход форматирующей строки со спецификацией преобразования %n пользователь сможет распечатать содержимое произвольных областей памяти. При распечатке соответствующей области памяти можно запустить программу с привилегиями привилегированного пользователя root.

Проверка программами Web-интерфейса, например CGI-программами, входных данных программы часто приводит к неожиданным результатам. Нередко недостаточно квалифицированно написанные CGI-программы (особенно это касается программ, написанных на языке Perl) позволяют выполнять команды, заключенные в специальные символы, что дает возможность выполнять произвольные команды системы с привилегиями Web-пользователя. В некоторых случаях это может привести к серьезным последствиям. Например, к удалению файла index.html, если HTTP-процесс является владельцем этого файла и имеет право писать в него данные. Или к предоставлению пользователю локального доступа к системе с разрешениями HTTP-процесса, если пользователь свяжет оболочку shell c произвольным портом системы.