Часть полного текста документа:Безопасное программирование на Perl Дмитрий Громов Как избежать передачи пользовательских переменных оболочке ОС при вызове exec() и system()? В Perl вы можете запускать внешние программы различными путями. Вы можете перехватывать вывод внешних программ, используя обратные кавычки: $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 () { print "match: $_"; } close GREP; Это те формы open(), которые необходимо всегда использовать в случаях, когда в другой ситуации вы использовали бы перенаправление open (piped open). Еще более хитрая возможность позволяет вам запускать внешние программы и обманывать их относительно их собственного названия. Это полезно при использовании программ, действия которых зависят от того, с использованием какого имени они запущены. Вот синтакс: system $настоящее_имя "ложное_имя","аргумент1","аргумент2" Например: $shell = "/bin/sh" system $shell "-sh","-norc" Этот пример запускает sh - оболочку операционной системы - с именем "-sh", заставляющим ее действовать интерактивно. Заметте, что настоящее имя программы должно храниться в виде переменной, и что между именем переменной и началом списка аргументов нет запятой. Можно записать эту команду более компактно: system { "/bin/sh" } "-sh","-norc" Что такое "проверки заразности" (taint checks) в Perl? Как их включить? Как мы видели, одна из наиболее часто встречающихся проблем с безопасностью при программировании CGI - передача оболочке ОС пользовательских переменных без их проверки. Perl предлагает механизм проверки "заразности", который не позволяет этого делать. Любая переменная, которая проинициирована данными за пределами программы (включая данные из среды, стандартного ввода и командной строки) рассматривается как "заразная", и не может быть более использована за пределами программы. ............ |