Perl禁用shell访问

时间:2015-11-15 21:31:12

标签: perl shell

如果传递包含shell元字符的单个参数,某些内置函数(如systemexec(以及反引号)将使用shell(我认为默认为sh)。如果我想编写一个可以避免对底层shell做出任何假设的可移植程序,是否有一个pragma或其他一些选项可用于禁用shell访问或立即触发致命错误?

2 个答案:

答案 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');