Безопасное выполнение системных команд при кодировании на Perl

Следует ли действительно использовать внешние команды при кодировании на Perl? Я вижу несколько недостатков этого. Это не зависит от системы плюс риски безопасности также могут быть там. Как вы думаете? Если нет способа и вам нужно использовать команды оболочки из Perl, то какой самый безопасный способ выполнить эту конкретную команду (например, проверить pid, uid и т. Д.)?

3 ответа

Решение

Это зависит от того, насколько сложно будет воспроизвести функциональность в Perl. Если бы мне нужно было запустить m4 Макропроцессор на чем-то, я бы не стал пытаться копировать эту функциональность в Perl сам, и, поскольку на http://search.cpan.org/ нет модуля, который выглядел бы подходящим, другие, похоже, со мной согласились. В таком случае использование внешней программы целесообразно. С другой стороны, если мне нужно прочитать содержимое каталога, то сочетание readdir() и др. плюс stat() или же lstat() внутри Perl более разумно, чем futzing с выходом ls,

Если вам нужно выполнить команды, очень тщательно продумайте, как вы их вызываете. В частности, вы, вероятно, хотите избежать интерпретации аргументов оболочкой, поэтому используйте форму массива system (смотрите также exec) и т. д., а не одна строка для команды плюс аргументы (что означает, что оболочка используется для обработки командной строки).

Выполнение внешних команд может быть дорогостоящим просто потому, что оно включает в себя создание нового процесса и отслеживание его вывода, если вам это нужно.

Возможно, что еще важнее, если по какой-либо причине внешний процесс завершится неудачей, может быть трудно понять, что произошло с помощью вашего сценария. Хуже того, на удивление часто внешний процесс может зависнуть навсегда, так же как и ваш сценарий. Вы можете использовать специальные приемы, такие как открытие канала и отслеживание вывода в цикле, но это само по себе подвержено ошибкам.

Perl очень способен на многое. Таким образом, если вы будете использовать только собственные конструкции и модули Perl для выполнения ваших задач, то не только это будет быстрее, потому что вы никогда не разветвляетесь, но и будет более надежным и более простым для выявления ошибок, если посмотреть на собственные объекты Perl и структуры, возвращаемые библиотечные процедуры. И, конечно, он будет автоматически переносим на разные платформы.

Если ваш скрипт запускается с повышенными правами (например, root или sudo), вы должны быть очень осторожны в отношении того, какие внешние программы вы выполняете. Один из простых способов обеспечения базовой безопасности - всегда указывать команды с полным именем, например /usr/bin/grep (но все же подумайте дважды и просто выполните grep для самого Perl!). Однако даже этого может быть недостаточно, если злоумышленник использует механизм LD_PRELOAD для внедрения мошеннических общих библиотек.

Если вы хотите быть очень безопасным, рекомендуется использовать проверку с испорченными данными с помощью флага -T, например:

#!/usr/bin/perl -T

Флаг Taint также будет включен Perl автоматически, если ваш сценарий будет иметь разные реальные и эффективные идентификаторы пользователей или групп.

Запятнанный режим сильно ограничит вашу способность делать многие вещи (например, вызов system()) без жалоб на Perl - см. Больше на http://perldoc.perl.org/perlsec.html, но это даст вам гораздо больше уверенность в безопасности.

Следует ли действительно использовать внешние команды при кодировании на Perl?

Там нет однозначного ответа на этот вопрос. Все зависит от того, что вы делаете в широком диапазоне потенциальных применений Perl.

Используете ли вы Perl в качестве прославленного сценария оболочки на локальном компьютере или просто пытаетесь найти быстрое и грязное решение вашей проблемы? В этом случае имеет смысл запускать системные команды, если это самый простой способ выполнить вашу задачу. Безопасность и скорость не так важны; важна способность быстро кодировать.

С другой стороны, вы пишете производственную программу? В этом случае вам нужен безопасный, переносимый, эффективный код. Часто предпочтительно писать функциональность в Perl (или использовать модуль), а не вызывать внешнюю программу. По крайней мере, вы должны хорошо подумать о преимуществах и недостатках.

Другие вопросы по тегам