19.6 Perl

本节主要介绍在Perl平台上获取用户提交的输入的方法、与用户会话交互的方式、存在的潜在危险的API以及与平台安全相关的配置选项。

众所周知,Perl语言允许开发者以各种方式执行相同的任务。而且,有大量Perl模块可满足不同的需求。如果Perl使用任何不常见的或所有权模块,应对这些模块进行仔细审查,确定它们是否使用了任何强大的或危险的函数,从而引入应用程序直接使用这些函数时引入的相同漏洞。

CGI.pm是最常用于创建Web应用程序的Perl模块,当对用Perl编写的Web应用程序进行代码审查时,很可能遇到这个模块所使用的API。

19.6.1 确定用户提交的数据

表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的数组,其中包含所有请求参数的名称与值

19.6.2 会话交互

Perl模块CGISession.pm对模块CGI.pm进行扩展,为会话追踪与数据存储提供支持。例如:

img566a

19.6.3 潜在危险的API

这一节介绍一些常见的Perl API。以危险的方式使用这些API可能会造成安全漏洞。

1.文件访问

Perl使用下面的API访问文件:

img002 open

img002 sysopen

open函数用于读取或写入指定文件的内容。如果以文件名参数提交用户可控制的数据,攻击者就可以访问服务器文件系统上的任意文件。

另外,如果文件名参数的开头或结尾为管道符(|),那么这个参数的内容被提交给一个shell命令。如果攻击者能够注入包含管道符或分号之类的shell元字符的数据,那么他们就可以执行任意命令。例如,在下面的代码中,攻击者可以注入$useraddr参数,以执行系统命令:

img566b

2.数据库访问

selectall_arrayref函数用于向数据库发送一个查询,并以一系列数组的形式检索查询结果。do函数用于执行一个查询,并返回受影响的行的数量。在这两个函数中,SQL语句以一个简单的字符串提交。

如果用户可控制的数据属于字符串参数的一部分,那么应用程序就可能容易受到SQL注入攻击。例如:

img566c

它会执行不良查询:

img567a

prepare与execute函数可用于创建预处理语句,允许应用程序建立一个包含参数占位符的SQL查询,并以可靠而且类型安全的方式设定这些占位符的值。如果按正常的方式使用,这种机制就不易受到SQL注入攻击。例如:

img567b

它生成的查询等同于:

img567c

3.动态代码执行

eval可用于动态执行包含Perl代码的字符串。分号分隔符用于将几个语句连接在一起。如果向这个函数提交用户可控制的数据,那么应用程序可能易于受到脚本注入攻击。

4.OS命令执行

下面这些函数可用于执行操作系统命令:

img002 system

img002 exec

img002 qx

img002 反单引号(`)

所有这些命令都可以使用 | 字符链接在一起。如果未经过滤就向这些函数提交用户可控制的数据,攻击者就可以在应用程序中执行任意命令。

5.URL重定向

CGI查询对象成员之一的redirect函数接受一个包含相对或绝对URL的字符串;用户被重定向到该URL。如果这个字符串的值由用户控制,那么应用程序可能易于受到钓鱼攻击。

6.套接字

使用socket创建一个套接字后,再通过调用connect在它与远程主机之间建立连接,connect函数接受由目标主机的IP与端口信息组成的sockaddr_in结构。如果用户能够以某种方式控制这些主机信息,攻击者就可以利用应用程序与任意主机建立网络连接,无论这些主机位于因特网上、私有DMZ中还是在应用程序上运行的内部网络内。

19.6.4 配置Perl环境

Perl提供一个污染模式,防止用户提交的输入被传送给潜在危险的函数。通过以下方式向Perl解释器提交-T标记,可在污染模式下执行Perl程序。

img568a

当某个程序在污染模式下运行时,解释器会追踪该程序以外提交的每一个输入,并把它当做被污染的输入处理。如果另一个变量根据一个受污染的数据分配它的值,那么Perl也认为它受到污染。例如:

img568b

不能将污染的变量提交给一系列功能强大的命令,包括eval、system、exec与open。要在敏感操作中使用污染的数据,就必须执行一项模式匹配操作并提取匹配的子字符串,“清洁”这些数据。例如:

img568c

虽然污染模式机制旨在防止许多类型的漏洞,但只有当开发者使用适当的正则表达式从被污染的输入中提取“清洁”的数据时它才会有效。如果一个表达式的范围过于宽泛,并提取了使用时可能引起问题的数据,那么污染模式提供的保护就会失效,应用程序仍然易于受到攻击。实际上,污染模式被当做一种提醒机制,它告诉程序员在危险操作中使用输入的数据前,必须对所有输入进行适当确认。它不能保证所实施的输入确认已经足够全面。