Perl程序员应该首先阅读perlsec(1)的man帮助页,那里描述了许多用Perl编写安全程序涉及的问题。特别是perlsec(1)描述了“污染”模式,大多数安全Perl程序应该使用该模式。如果真实的用户或群组ID与有效用户或群组ID不同,或者使用了命令行标识-T (在以其他人身份运行程序如CGI脚本时使用后一种方式),则自动启用污染模式。污染模式会打开各种检查,如检查路径目录以确定它们对其他人是不可写的。
尽管如此,污染模式最明显的效果是不可以使用来自程序以外的数据来偶然影响程序之外的事情。在污染模式下,所有外部获得的输入,包括命令行参数、环境变量、本地信息(参见perllocale(1))、特定系统调用(readdir、readlink、getpw*调用的gecos域)的结果和所有文件输入,都被标记为“被污染”。被污染的数据不可以直接或间接地被应用在执行子shell的命令里,或者被用在修改文件、目录或进程的命令里。一个重要的例外:如果向system或exec传递一个参数列表,该列表中的成员不会被检查是否被污染,所以在污染模式下使用system或exec要特别小心。
来自被污染数据的任何数据值也是被污染的。这里有一个例外;从被污染的数据中提取一个子字符串可以使数据不被污染。但也不要盲目地采用“.*”作为子字符串,因为这样会失去污染机制的保护。作为替代,应该识别出程序允许的“安全”模板,并用它们来提取“好的”值。在提取出值之后,可能还需要对它进行检查(特别是它的长度)。
open、glob和backtick函数调用shell来扩展文件名里的通配符;这可被用来打开安全漏洞。应该尽量完全避免这些函数,或者在perlsec(1)里描述的低权限的“沙箱”里使用它们。
坦白地说,Perl的open()函数对于大多数安全程序而言“有太多的魔法”;如果没有小心地过滤,它在解释文本时会制造很多安全问题。在编写打开或锁定某个文件的代码之前,请参考perlopentut(1)的man帮助页。在大多数情况下,sysopen()提供了打开文件的一个更安全(虽然更为错综复杂)的方法。 新的Perl 5.6增加了有三个参数的open()调用,去掉了有魔力的行为,从而不需要错综复杂的sysopen()。
Perl程序应该打开告警标志(-w),来警告有潜在危险的或过时的语句。
也可以在受限制的环境下运行Perl程序。更多的信息可参见标准Perl发行版中的“安全”模块。我不能确定对它进行的审计情况,所以用户需要注意。也可以调查一下“安全的分布式Internet脚本编写的企鹅模型”,虽然在写作本文时其代码和文档还无法得到。