10.2. Perl

Perl 程序员应该首先阅读 perlsec(1) 手册页,其中描述了使用 Perl 编写安全程序时涉及的许多问题。特别是,perlsec(1) 描述了“污点”模式,大多数安全的 Perl 程序都应该使用它。如果实际用户 ID 或组 ID 与有效用户 ID 或组 ID 不同,则会自动启用污点模式,或者您可以使用 -T 命令行标志(如果您代表其他人运行,例如 CGI 脚本,则使用后者)。污点模式会开启各种检查,例如检查路径目录以确保它们不可被其他人写入。

然而,污点模式最明显的影响是,您可能不会意外地使用来自程序外部的数据来影响程序外部的其他事物。在污点模式下,所有外部获取的输入都被标记为“污点”,包括命令行参数、环境变量、区域设置信息(参见 perllocale(1))、某些系统调用的结果(readdir、readlink、getpw* 调用的 gecos 字段)以及所有文件输入。污点数据不得直接或间接地用于任何调用子 shell 的命令,也不得用于任何修改文件、目录或进程的命令。有一个重要的例外:如果您将参数列表传递给 system 或 exec,则该列表的元素不会检查是否被污点,因此在污点模式下使用 system 或 exec 时要格外小心。

任何从污点数据派生的数据值也会变为污点。对此有一个例外;解除数据污点的方法是提取污点数据的子字符串。但不要盲目地使用“.*”作为子字符串,因为这会破坏污点机制的保护。相反,识别出程序允许的“安全”模式的模式,并使用它们来提取“良好”的值。提取值后,您可能仍然需要检查它(特别是其长度)。

open、glob 和反引号函数调用 shell 来展开文件名通配符;这可能会被用来打开安全漏洞。您可以尝试完全避免这些函数,或者在 perlsec(1) 中描述的特权较低的“沙箱”中使用它们。特别是,反引号应该使用 system() 调用重写(或者更好的是,完全更改为更安全的东西)。

坦率地说,perl open() 函数为大多数安全程序带来了“太多的魔法”;它解释文本,如果未仔细过滤,可能会产生许多安全问题。在编写代码以打开或锁定文件之前,请查阅 perlopentut(1) 手册页。在大多数情况下,sysopen() 提供了一种更安全(但更复杂)的打开文件方法。新的 Perl 5.6 添加了一个带有 3 个参数的 open() 调用,以关闭魔法行为,而无需 sysopen() 的复杂性

Perl 程序应该打开警告标志 (-w),这会警告潜在的危险或过时的语句。

您也可以在受限环境中运行 Perl 程序。有关更多信息,请参阅标准 Perl 发行版中的“Safe”模块。我不确定这已经经历了多少审计,因此请注意不要依赖它来确保安全。您也可以研究“安全分布式互联网脚本的 Penguin 模型”,尽管在撰写本文时,代码和文档似乎不可用。

许多安装都包含一个 setuid root 版本的 perl,名为“suidperl”。然而,perldelta 手册页 5.6.1 版本建议使用 sudo 代替,并说明如下:

“请注意,在任何最近版本的 perl 中,默认情况下都不会构建或安装 suidperl。强烈建议不要使用 suidperl。如果您认为需要它,请首先尝试 sudo 等替代方案。请参阅 http://www.courtesan.com/sudo/”。