用于本节我们所讨论的所有问题的过滤用户输入的一个通常方法(FUIn OCA )就是过滤任何不需要的转换字符和有问题的数据。例如我们可以在任何时段过滤来避免向后的目录查看。类似的,我们一旦看见非法的字符,就让程序运行失败,这种策略被称为”黑名单”这种哲学就是如果某东西没有明确禁止,那它肯定是好的。一个更好的策略就”白名单”,它指如果某东西没有被明确认可,那么它必须禁止。黑明单的最重要的问题是它非常难保持完整性并得到更。你也许会忘掉过滤某一特定字符,或者你的程序或许不得不随不同的转换字符集合转到一个不同shell中。不过滤掉不需要的转换字符和其他危险输入,相反,只过滤进合法的输入。下面的片段就是一个例子,它会停止执行一个安全性有问题的操作,如果有户输入中包含了除字母,数字,点和@符号外任何东西(@经常用于用户的电子邮件地址)
unless($useradress=~/^[-@/w。]+)$/)
{print”secrity error。/n”exit(1);
}
基本的思想是不去编译一个特定值的列表来保护,而是产生一个安全列表来接受可接受的输入值的列表。可接受的输入输入值的选择当然会随着不同的应用程序而变化。可接受的值应该采用某种能将破坏的可能性降到最小的方式来选择。
避免shell
当然,你也必须尽可能的避免shell,然而这种技术可被广泛地应用。如果你调用一个有特定序列的编辑器。你必须确认这些特定序列是不被允许使用的。一般,通过使用现存perl模块,你能避免使用外部程序来执行一个外部函数,CPAN是一个能完成几乎所有标准UNIX工具集能做的任何事的经测试的函数的模块来源,然而它或许会费点劲来包含一个模块,并且调用它,而不是调用一个外部程序,模块方法一般来说更安全和灵活,为解释清楚这一点,使用Net::SMTP,而不用exec()’ing sendmail/--T会帮你少一些使用shell的麻烦,并能防止你的用户在sendmail代理中寻求已知的弱点。
其它安全问题的来源(不安全环镜变量)
用户输入实际上是perl程序的主要安全问题的来源,但是还有其它因素是在写安全的perl源代码时所必须考滤的,经常 在shell下运行的脚本的易受攻击的弱点或者通过网络服务器是不安全的环镜变量,最通常的是PATH /变量。当你从你代码内部中使用一个外部应用程序或功能,而仅仅指明了一条相对路径的时候,你就使 你这个程序和运行它的系统处于危险中。如果你有如下一个system()调用:
system(“txt2html”,”user/stats/jdiov”);
对于这种调用,你假设txt2htm文件是包含在PATH变量某处的目录下,但是假如发生这种情况,一个攻击者改变你的路径指向含有相同的名字的其他带恶意的程序中,你的系统的安全性就得不到保证。为了避免例似的事情发生,每个需要含有远程安全意识的程序都应该这样开始写:
#!/usr/bin/perl -wT
require 5.001;
use strict;
$ENV = join ':' => split (" ", << '__EOPATH__');
/usr/bin
/bin
/maybe/something/else
__EOPATH__
如果程序依赖于其他环境变量,它们也要在它们使用前明确的定义出来。
另一个危险变量(这个更是针对perl的)是@INC距阵变量,它非常像PATH,只不过它 指明Perl到哪里去找要包含在程序中的模块。有关@INCR 的问题和PATH是非常相似的。有人可能会把你的perl指向一个具有相同的名字模块,而且如你所料的做同样的事,但是它也背地里做一些坏事,因此@INC同PATH都不值的信任。在包括任何外部模块之前都 必须完全重新定义。
Setuid脚本