本节主要介绍在Perl平台上获取用户提交的输入的方法、与用户会话交互的方式、存在的潜在危险的API以及与平台安全相关的配置选项。
众所周知,Perl语言允许开发者以各种方式执行相同的任务。而且,有大量Perl模块可满足不同的需求。如果Perl使用任何不常见的或所有权模块,应对这些模块进行仔细审查,确定它们是否使用了任何强大的或危险的函数,从而引入应用程序直接使用这些函数时引入的相同漏洞。
CGI.pm是最常用于创建Web应用程序的Perl模块,当对用Perl编写的Web应用程序进行代码审查时,很可能遇到这个模块所使用的API。
表19-11列出了CGI查询对象的全部成员。
表19-11 用于获取用户提交的数据的CGI查询成员
选 项 | 描 述 |
---|---|
param param_fetch |
如果调用时不使用参数,param返回请求中所有参数名称的列表 如果调用时使用参数名称,param返回该请求参数的值 param_fetch方法返回一个命名参数数组 |
Vars | 它返回参数名称与值之间的散列映射 |
cookie raw_cookie |
使用cookie函数可设定和检索一个命名cookie的值 raw_cookie函数返回HTTP Cookie消息头的全部内容,但不进行任何解析 |
self_url url |
这些函数返回当前URL,前者包含所有查询字符串 |
query_string | 这个函数返回当前请求的查询字符串 |
referer | 这个函数返回HTTP Referer消息头的值 |
request_method | 这个函数返回请求中使用的HTTP方法 |
user_agent | 这个函数返回HTTP User_agent消息头的值 |
http https |
这些函数返回当前请求中的所有HTTP环境变量列表 |
ReadParse | 这个函数返回一个名为%in的数组,其中包含所有请求参数的名称与值 |
Perl模块CGISession.pm对模块CGI.pm进行扩展,为会话追踪与数据存储提供支持。例如:
这一节介绍一些常见的Perl API。以危险的方式使用这些API可能会造成安全漏洞。
1.文件访问
Perl使用下面的API访问文件:
open
sysopen
open函数用于读取或写入指定文件的内容。如果以文件名参数提交用户可控制的数据,攻击者就可以访问服务器文件系统上的任意文件。
另外,如果文件名参数的开头或结尾为管道符(|),那么这个参数的内容被提交给一个shell命令。如果攻击者能够注入包含管道符或分号之类的shell元字符的数据,那么他们就可以执行任意命令。例如,在下面的代码中,攻击者可以注入$useraddr参数,以执行系统命令:
2.数据库访问
selectall_arrayref函数用于向数据库发送一个查询,并以一系列数组的形式检索查询结果。do函数用于执行一个查询,并返回受影响的行的数量。在这两个函数中,SQL语句以一个简单的字符串提交。
如果用户可控制的数据属于字符串参数的一部分,那么应用程序就可能容易受到SQL注入攻击。例如:
prepare与execute函数可用于创建预处理语句,允许应用程序建立一个包含参数占位符的SQL查询,并以可靠而且类型安全的方式设定这些占位符的值。如果按正常的方式使用,这种机制就不易受到SQL注入攻击。例如:
它生成的查询等同于:
3.动态代码执行
eval可用于动态执行包含Perl代码的字符串。分号分隔符用于将几个语句连接在一起。如果向这个函数提交用户可控制的数据,那么应用程序可能易于受到脚本注入攻击。
4.OS命令执行
下面这些函数可用于执行操作系统命令:
system
exec
qx
反单引号(`)
所有这些命令都可以使用 | 字符链接在一起。如果未经过滤就向这些函数提交用户可控制的数据,攻击者就可以在应用程序中执行任意命令。
5.URL重定向
CGI查询对象成员之一的redirect函数接受一个包含相对或绝对URL的字符串;用户被重定向到该URL。如果这个字符串的值由用户控制,那么应用程序可能易于受到钓鱼攻击。
6.套接字
使用socket创建一个套接字后,再通过调用connect在它与远程主机之间建立连接,connect函数接受由目标主机的IP与端口信息组成的sockaddr_in结构。如果用户能够以某种方式控制这些主机信息,攻击者就可以利用应用程序与任意主机建立网络连接,无论这些主机位于因特网上、私有DMZ中还是在应用程序上运行的内部网络内。
Perl提供一个污染模式,防止用户提交的输入被传送给潜在危险的函数。通过以下方式向Perl解释器提交-T标记,可在污染模式下执行Perl程序。
当某个程序在污染模式下运行时,解释器会追踪该程序以外提交的每一个输入,并把它当做被污染的输入处理。如果另一个变量根据一个受污染的数据分配它的值,那么Perl也认为它受到污染。例如:
不能将污染的变量提交给一系列功能强大的命令,包括eval、system、exec与open。要在敏感操作中使用污染的数据,就必须执行一项模式匹配操作并提取匹配的子字符串,“清洁”这些数据。例如:
虽然污染模式机制旨在防止许多类型的漏洞,但只有当开发者使用适当的正则表达式从被污染的输入中提取“清洁”的数据时它才会有效。如果一个表达式的范围过于宽泛,并提取了使用时可能引起问题的数据,那么污染模式提供的保护就会失效,应用程序仍然易于受到攻击。实际上,污染模式被当做一种提醒机制,它告诉程序员在危险操作中使用输入的数据前,必须对所有输入进行适当确认。它不能保证所实施的输入确认已经足够全面。