如果传递包含shell元字符的单个参数,某些内置函数(如system
和exec
(以及反引号)将使用shell(我认为默认为sh
)。如果我想编写一个可以避免对底层shell做出任何假设的可移植程序,是否有一个pragma或其他一些选项可用于禁用shell访问或立即触发致命错误?
答案 0 :(得分:4)
我在Mastering Perl中广泛地写了这篇文章。简短的回答是在其列表表单中使用system
。
system '/path/to/command', @args;
这并不能解释@args
中的任何特殊字符。
同时,在将错误数据传递给系统之前,应启用污点检查以帮助捕获错误数据。有关详细信息,请参阅perlsec文档。
答案 1 :(得分:0)
执行此操作的选项有限,请记住,这些是核心例程,完全禁用它们可能会产生一些意想不到的后果。你有几个选择。
本地覆盖
您可以使用subs
pragma在本地覆盖system和exec,这只会影响您导入子例程的包:
#!/usr/bin/env perl
use subs 'system';
sub system { die('Do not use system calls!!'); }
# .. more code here, note this will runn
my $out = system('ls -lah'); # I will die at this point, but not before
print $out;
全局覆盖
要全局覆盖,在当前的perl进程中,需要在编译时将函数导入CORE :: GLOBAL伪命名空间:
#!/usr/bin/env perl
BEGIN {
*CORE::GLOBAL::system = sub {
die('Do not use system calls.');
};
*CORE::GLOBAL::exec = sub {
die('Do not use exec.');
};
*CORE::GLOBAL::readpipe = sub {
die('Do not use back ticks.');
};
}
#...
my $out = system('ls -lah'); # I will die at this point, but not before
print $out;
防止任何形式在源
中运行如果您想在开始系统调用之前阻止任何代码运行,您可以包含以下内容,请注意它的匹配相当宽松,我已将其编写为易于修改或更新:
package Acme::Noshell;
open 0 or print "Can't execute '$0'\n" and exit;
my $source = join "", <0>;
die("Found back ticks in '$0'") if($source =~ m/^.*[^#].*\`/g);
die("Found 'exec' in '$0'") if($source =~ / exec\W/g);
die("Found 'system' in '$0'") if($source =~ / system\W/g);
1;
可以使用如下:
#!/usr/bin/env perl
use strict;
use warnings;
use Acme::Noshell;
print "I wont print because of the call below";
my $out = system('ls -lah');