Наверх, к Содержание | ||
Назад, к Скрипты CGI | Вперед,
к Запись истории сервера и частная жизнь |
$date = `/bin/date`;
Вы можете открывать "туннель" (pipe) к программе:
open (SORT, " | /usr/bin/sort | /usr/bin/uniq");Вы можете запускать внешние программы и ждать окончания их выполнения через system():
system "/usr/bin/sort < foo.in";или вы можете запускать внешние программы без возврата управления с помощью exec():
exec "/usr/bin/sort < foo.in";Все эти выражения являются опасными если используют данные, введенные пользователем, которые могут содержать метасимволы. Для system() и exec() существует синтаксическая возможность, позволяющая запускать внешние программы напрямую, без обращения к оболочке ОС. Если вы передаете внешней программе аргументы, представляющие собой не строку, а список, то Perl не будет использовать оболочку, и метасимволы не вызовут нежелательных побочных эффектов. Например:
system "/usr/bin/sort","foo.in";Вы можете использовать эту особенность для того, чтобы открыть туннель, не обращаясь к оболочке ОС. Вызывая open в магической последовательности символов
|-
, вы запускаете копию Perl и открываете туннель (pipe) к этой
копии. Дочерняя копия Perl затем немедленно запускае внешнюю программу,
используя список аргументов для exec(). open (SORT,"|-") || exec "/usr/bin/sort",$uservariable; while $line (@lines) { print SORT $line,"\n"; } close SORT;Для чтения из туннеля без обращения к оболочке можно использовать похожий способ, с последовательностью
-|
: open(GREP,"-|") || exec "/usr/bin/grep",$userpattern,$filename; while (<GREP>) { print "match: $_"; } close GREP;Это те формы open(), которые необходимо всегда использовать в случаях, когда в другой ситуации вы использовали бы перенаправление open (piped open).
Еще более хитрая возможность позволяет вам запускать внешние программы и обманывать их относительно их собственного названия. Это полезно при использовании программ, действия которых зависят от того, с использованием какого имени они запущены.
Вот синтакс:
system $настоящее_имя "ложное_имя","аргумент1","аргумент2"Например:
$shell = "/bin/sh"Этот пример запускает sh - оболочку операционной системы - с именем "-sh", заставляющим ее действовать интерактивно. Заметте, что настоящее имя программы должно храниться в виде переменной, и что между именем переменной и началом списка аргументов нет запятой.
system $shell "-sh","-norc"
Можно записать эту команду более компактно:
system { "/bin/sh" } "-sh","-norc"
В версии 4 языка Perl проверка включается при использовании специальной версии интерпретатора, называющейся "taintperl":
#!/usr/local/bin/taintperlВ версии 5 - используйте флаг -T при запуске интерпретатора:
#!/usr/local/bin/perl -TНиже описано как "обеззараживать" (untaint) переменные.
Для более полного обсуждения вопроса можно обратиться к CGI/Perl Taint Mode FAQ (автор - Gunther Birzniek).
$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin';Отредактируйте ее так, чтобы перечислить директории, в которых вы хотите искать. Мысль о вклюяении текущего директория (".") в состав переменной PATH является плохой идеей.
$mail_address=~/(\w[\w-.]*)\@([\w-.]+)/; $untainted_address = "$1\@$2";Такая маска позволит выделить адрес в форме "кому@куда", где элементы "кому" и "куда" могут включать литеры, точки и тире. Более того, "кому" не может начинаться с тире, используемого во многих программах как служебный символ командной строки.
$foo=~/$user_variable/
?foreach (@files) {Теперь, однако, Perl будет игнорировать любые изменения в переменной, что приведет к неправильной работе циклов такого рода:
m/$user_pattern/o;
}
foreach $user_pattern (@user_patterns) { foreach (@files) { print if m/$user_pattern/o; } }Для обхода этой проблемы программисты, пишущие на Perl, часто используют такой трюк:
foreach $user_pattern (@user_patterns) { eval "foreach (\@files) { print if m/$user_pattern/o; }"; }Проблема здесь состоит в том, что в операторе eval() используется пользовательская переменная. Если переменная не подвергается тщательной проверке, то можно заставить eval() выполнить произвольный код на Perl. Для понимания того, чем это грозит, подумайте, что произойдет в случае, если переменная будет иметь следующее значение:
"/; system 'rm *'; /"
Проверки заразности (см. выше) позволяют поймать потенциальную опасность в этой области. Вы можете выбирать между отказом от такого рода оптимизации, или тщательным обеззараживанием переменной перед использованием. Полезная возможность в Perl5 состоит в использовании \Q и \E для комментирования метасимволов так, чтобы они не были использованы:
print if m/\Q$user_pattern\E/o;
Вы можете заставить скрипт выполняться с правами его владельца путем установки бита s:
chmod u+s foo.plВы можете предоставить ему права группы, к которой принадлежит владелец, установив бит s в поле группы:
chmod g+s foo.plОднако, многие системы Unix содержат лазейку, позволяющую взламывать такие скрипты. Это касается только скриптов, а не компилированных программ. В таких системах попытка запуска скрипта на Perl, для которого были выставлены s биты, приведет к появлению сообщения об ошибке со стороны самого Perl.
На таких системах вы имеете две возможности:
#include <unistd.h> void main () { execl("/usr/local/bin/perl","foo.pl","/local/web/cgi-bin/foo.pl",NULL); }После компилирования программы, выставте s биты. Программа будет выполняться с правами владельца, запускать интерпретатор Perl и выполнять скрипт, содержащийся в файле "foo.pl".
Кроме того, можно запускать сам сервер с правами пользователя, достаточными для выполнения необходимых действий. Если вы используете сервер CERN, то у вас есть возможность запускать сервер с разными правами для разных скриптов. См. документацию CERN для получения дальнейшей информации.
Наверх, к Содержание | ||
Назад, к Скрипты CGI | Вперед,
к История сервера и частная жизнь |
Lincoln D. Stein (lstein@w3.org)
Перевод - Дмитрий Громов
Last modified: Tue Jun 30 21:20:38 EDT 1998