Perl – Taint() 方法
在 Perl 中,污点模式是一种使我们的代码更安全的方法。它使我们的程序对从外部源接收的数据更加挑剔。外部源是指用户、文件系统、环境、区域信息和一些系统调用。污染模式是为安全性很重要的情况而创建的,例如编写运行 root 或 CGI 脚本的 Perl 程序。人们应该总是在他们的 CGI 脚本中使用污点模式。
某些功能会意外导致错误数据出现问题。确保程序正在打开我们希望它打开的文件,而不是像恶作剧用户提供的命令之类的其他东西,这符合我们的利益。
使用 Taint() 方法
要打开污点模式,我们只需在 hashbang 行中使用-T 标志。
#!/usr/bin/perl -wT
污点模式用于跟踪来自用户的数据,并避免对其进行任何不安全的操作。启用后,Perl 会监视每个变量以检查它是否被污染。受污染的数据是来自代码之外的任何数据。
由于它涵盖了从STDIN读取的所有内容以及所有环境变量,因此它包括来自服务器的 CGI 脚本接收器的所有内容。因此,遵守 Perl 不允许在任何影响外部文件的 Perl 命令中使用任何用户输入的值。
污点模式不允许来自应用程序外部的数据影响应用程序外部的任何内容。
Taint()是Scalar::Util模块的一个函数,可用于检查变量是否被污染,以及使用它会触发“不安全依赖”消息。
污染源()
每当给定系统中存在安全漏洞时,首先检查程序的攻击面。攻击面是暴露给攻击者的程序部分。
污染源是程序中从潜在风险源读取数据的位置,包括环境变量、数据、文件、网络服务等。
攻击者可以使用这些未经验证的通道来触发安全漏洞或导致问题崩溃。因此,为避免这种情况,需要进行污点分析。通过消除可利用的攻击面,这是一种降低风险因素的有效方法。
去除污点()
如果没有一种方法可以消除我们的数据的污染,那么污染模式就会受到如此多的限制。但是,当然,人们不想在不检查数据的安全性的情况下对数据进行污染。幸运的是,Perl 中有一个命令可以让我们完成这两项任务。 Perl 不允许涉及污染值的表达式计算为未污染值。
因此,清除受污染变量的唯一方法是对其执行模式匹配操作,然后提取匹配的子字符串。如果我们用正则表达式匹配一个变量,那么与匹配的括号对应的匹配变量是不受污染的(如 $1、$2 等)。
例如:如果我们希望一个变量包含一个电子邮件地址,那么我们可以通过以下方式提取该地址的未污染副本:
Perl
$mail_address=~/(\S+)\@([\w.-]+)/;
$untainted_address = "$1\@$2";
Perl
# Showing how a variable assigned to
# a tainted value gets tainted itself too:
#!/usr/bin/perl -T
my $arg = $ARGV[0];
my $file = "/home/foo/$arg";
open FOO, ">$file" or die $!;
print FOO "Yay\n";
close FOO;
exit 0;
解释:在上面的例子中,第一个括号包围 (\w{1}[\w-.]*) 匹配一个或多个单词字符、破折号和句点,其前面至少有一个单词字符,不包含破折号或期间。括号使第一个匹配项在 Perl 中分配给 $1。
然后,匹配一个@ 符号。最后,第二组括号 ([\w-.]+) 匹配更多的单词字符、破折号和句点。第二场比赛分配给 $2。
因此,当正则表达式成功时,$1 将等于电子邮件地址的用户名部分,$2 将等于域部分。
Perl 认为这些变量是特殊的,因为 Perl 基本上认为,由于这些变量是由我们设置的正则表达式产生的,因此我们已经明确地检查了该正则表达式中数据的有效性。因此,1 美元和 2 美元不被认为是受污染的。
从环境中移除 Taint()
哪些数据被污染的问题取决于执行环境。例如,数据库的数据可能会或可能不会被认为是受污染的。 Perl 有一个 DBI 模块,该模块具有可选的Taintout属性,当设置该属性时,将从数据库接收到的所有数据都视为已污染。同样,有一组特定的操作不应该在完全依赖于执行环境的受污染数据上执行。
默认情况下,从模块导入符号会打开污点检查。如果希望在不需要污点检查(从环境中删除污点)的情况下使用此模块,我们可以通过以下方式进行:
- 通过使用(允许在没有 -T 的情况下运行)。
# allow to run without -T
use Taint qw(allow_no_taint);
# default import list
use Taint;
- 通过显式传递一个空的导入列表来不导入任何符号。
# importing no symbols
use Taint ();
一个显示污点模式实现的基本程序:
Perl
# Showing how a variable assigned to
# a tainted value gets tainted itself too:
#!/usr/bin/perl -T
my $arg = $ARGV[0];
my $file = "/home/foo/$arg";
open FOO, ">$file" or die $!;
print FOO "Yay\n";
close FOO;
exit 0;
该程序将失败并出现以下错误:
Insecure dependency in open while running with -T switch at ./test.pl line 9.