ПИШЕМ БАЖНУЮ CGI'ШКУ НА PERL

Спецвыпуск Xakep, номер #022, стр. 022-024-2


Если ты думаешь что таких ошибок нигде не встретить, то ты сильно ошибаешься. Добрая половина бесплатных скриптов, написанных за полчаса, содержит подобные ошибки. Надо просто внимательно смотреть. В некоторых скриптах допускаются еще более грубые ошибки, позволяющие выполнять команды.

Строка, заключенная между обратными кавычкам (``), передается операционной системе для выполнения. Если скрипт не проверяет, что там передается, то мы получаем возможность выполнить любую команду. В нашем скрипте мы передаем параметр $date, который необходим для вставки даты в письмо:

print OUT "Date: " . `/bin/$date` . "\n";

Если в качестве параметра в $date передадим любую другую команду, то она выполнится.

Функция eval() выполняет полученную строку как perl-команду. В некоторых скриптах встречается использование внешней переменной внутри eval. Например:

eval("$gbname");

В параметре $gbname мы можем передать любые perl-команды, и они выполнятся. У нас в гостевой книге такой дыры нету просто потому, что я уже не смог придумать, куда ее вставить :).

ПОСЫЛАЕМ!

В нашей гостевой книге, конечно, не обойтись без отправки комментариев на почту. И, естественно, мы сталкиваемся с очередным багом. На этот раз это связанно со старой, как мир, программой sendmail. Посмотрим наш скрипт:

open(MAIL,"|$mailprog $to -s $subject");

Ты удивишься, но в этой одной строке у нас сразу две ошибки! Смотри, мы запускаем sendamil с параметром $to, который берется из формы и является адресом получателя. Параметр $subject также берется из формы и является темой сообщения.

Теперь, если в теме сообщения написать, скажем, "test;ls -s /", perl выполнит, передаст ОС следующую строку:

sendmail moof@real.xakep.ru -s test;ls -s /

И что? А то, что выполнится команда "ls -s" - и мы получим содержимое каталога. Опять же вместо "ls -s" можно написать любую команду (а нужно ли?).

И второй баг. Он очень похож на первый, и вдвоем они, я думаю, никогда в скриптах не встречаются, а вот поодиночке очень даже часто. Теперь мы вставим выполнение команды вместо адреса $to, например:

moof@real.xakep.ru ls -s > gb.cgi

И опять получим все содержимое каталога себе на мыло.

ЗАКЛЮЧЕНИЕ.

Как видишь, большинство ошибок сделано только из-за лени программиста. Из-за того, что он решил не проверять получаемые значения. Стоило ему вырезать все спецсимволы с кодом 0 из полученных данных, и от первой ошибки мы бы избавились. А вырезать очень просто:

$gbname = ~s/\0//g;

А еще было бы здорово экранировать все спецсимволы, использующиеся в ос unix:

& ; ' ` \ " * ? < > ^ ( ) { } $ \n \r

Кроме того, perl имеет встроенные возможности предупреждения о потенциально опасных конструкциях. Для этого существует специальный механизм меченных данных. Меченные данные это все переменные, которые perl-скрпит получил извне (например, из формы). Perl не будет использовать эти данные, пока они не будут проверены. Для включения безопасного режима достаточно указать ключ -T в заголовке скрипта:

Назад на стр. 022-024-1  Содержание  Вперед на стр. 022-024-3