Наверх, к Содержание | ||
Назад, к Скрипты 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) {
m/$user_pattern/o;
}
Теперь, однако, Perl будет игнорировать любые изменения в переменной, что
приведет к неправильной работе циклов такого рода:
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.
На таких системах вы имеете две возможности:
ftp://rtfm.mit.edu/pub/usenet-by-group/comp.lang.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