Укрощение @Интернет@

       

Техника фильтрации


Существует два подхода к фильтрации пользовательского ввода:

а) выдача сообщения об ошибке и прекращение работы, если обнаружен хотя бы один опасный символ;

б) "выкусывание" всех таких символов без выдачи предупредительных сообщений и продолжение работы.

Последний подход неоправданно популярен вопреки логике и здравому смыслу. Почему? Пусть, например, адрес легального посетителя выглядит так: "horn&hoff@mail.org" Программа фильтрации "видит" потенциально опасный символ "&" и "на всякий случай" решает его удалить, - в результате письмо направляется совсем по другому адресу, а пользователь "ждет у моря погоды", не понимая почему оно до него не дошло.

Если встретился опасный символ – независимо от того, умышленно он вставлен или нет, – использовать такие данные нельзя. Скрипт обязан прекратить работу и объяснить причину своего неудовольствия пользователю.

Поиск заданного перечня символов легче всего осуществляется использованием регулярных выражений, например, так:

if ($filename =~/[<>\|\-&\.\\\/\0]/)

{die "Ошибка ввода! Недопустиый символ \"$&\" \n";}

open(fh, $filename);

...

Перечень потенциально опасных символов зависит от конкретного случая, – создание универсального фильтра "на все случаи жизни" невозможно.

Например, при добавлении новой записи в гостевую книгу разумно выполнить проверку на предмет присутствия "нехороших" тегов, но не стоит запрещать посетителям использовать теги вообще. В то же время, передавая e-mail посетителя внешнему МТА, необходимо убедится в отсутствии символов перенаправления стандартного ввода (синтаксически неотличимых от угловых скобок, обрамляющих тэги), иначе злоумышленник сможет ввести нечто вроде "hacker2000@hotmail.com; mail hacker2000@hotmail.com </www/cgi-bin/mycgi.pl" и получить исходный текст скрипта (или любого другого файла) "с доставкой на дом"!


Поиск уязвимых мест в скриптах значительно облегчает механизм меченных данных (tainted data). Если запустить Perl с ключом "-T", он станет требовать явной инициализации или фильтрации всех скалярных переменных, передаваемых функциям eval, system, exec и некоторым другим, потенциально опасным с его точки зрения. Любые переменные, полученные извне (стандартный поток ввода, командная строка, переменные окружения и т.д.), считаются "зараженными" и не могут быть переданы "опасным" функциям до тех пор, пока не будут "обеззаражены" фильтром регулярных выражений. Если одна "зараженная" переменная присваивается другой – та тоже становится "зараженной"!

Но Perl не проверяет корректности фильтрации символов, допуская даже сквозную фильтрацию – "(.*)", и не считает опасной функцию print

(как, впрочем, и многие другие). Конструкция "$a=<>; print $a" не вызывает нареканий со стороны Perl, а ведь переменная $a может содержать нехорошие тэги и вызовы SSI!

Механизм меченных данных, во всяком случае, его реализация в языке Perl, – не панацея! И расслабляться программистам не стоит. "Зараженный режим" разумно использовать как дополнительное средство самоконтроля, но если он не нашел никаких ошибок, это еще не дает оснований считать, что их там действительно нет. Сказанное относится и к ключу "-w", заставляющего Perl выполнять дополнительные проверки, "ругаться" при попытке чтения неинициализированных переменных, попытке модификации файловых манипуляторов и т.д., – если это и усилит безопасность программы, то на самую малость.


Содержание раздела