10.1 注入操作系统命令

大多数Web服务器平台发展迅速,现在它们已能够使用内置的API与服务器的操作系统进行几乎任何必需的交互。如果正确使用,这些API可帮助开发者访问文件系统、连接其他进程、进行安全的网络通信。但是,许多时候,开发者选择使用更高级的技术直接向服务器发送操作系统命令。由于这些技术功能强大、操作简单,并且通常能够立即解决特定的问题,因而具有很强的吸引力。但是,如果应用程序向操作系统命令传送用户提交的输入,那么就很可能会受到命令注入攻击,由此攻击者能够提交专门设计的输入,修改开发者想要执行的命令。

常用于发出操作系统命令的函数,如PHP中的exec和ASP中的wscript.shell函数,通常并不限制命令的可执行范围。即使开发者准备使用API执行相对善意的任务,如列出目录的内容,攻击者还是可以对其进行暗中破坏,从而写入任意文件或启动其他程序。通常,所有的注入命令都可在Web服务器的进程中安全运行,它具有足够强大的功能,使得攻击者能够完全控制整个服务器。

许多非定制和定制Web应用程序中都存在这种命令注入缺陷。在为企业服务器或防火墙、打印机和路由器之类的设备提供管理界面的应用程序中,这类缺陷尤其普遍。通常,因为操作系统交互允许开发者使用合并用户提交的数据的直接命令,所以这些应用程序都对交互过程提出了特 殊的要求。

10.1.1 例1:通过Perl注入

以下面的Perl CGI代码为例,它是一个用于服务器管理的Web应用程序代码的一部分。这项功能允许管理员在服务器上指定一个目录,并查看它的磁盘使用情况:

img284a

如果按设想的方式运行,这段脚本将把用户提交的dir参数值附加在预先设定的命令后面,执行命令并显示结果,如图10-1所示。

img284b

图10-1 一个列出目录内容的简单应用程序功能

然而,通过提交专门设计的、包含shell元字符的输入,攻击者可对这项功能进行各种方式的利用。对处理命令的解释器而言,这些字符有着特殊的含义,并可破坏开发者想要执行的命令。例如,管道符“|”可用于将一个进程的输出重定向为另一个进程的输入,从而将几个命令连接在一起。攻击者可以利用这种行为注入另外一个命令并获得输出结果,如图10-2所示。

img285a

图10-2 一个成功的命令注入攻击

在这个攻击中,最初的du命令的输出已被重定向为cat/etc/passwd命令的输入。不过,这个命令不会理睬上述输入,而是执行自己的任务:输出passwd文件的内容。

这样简单的攻击似乎是不可能的;但是,实际上在众多商业产品中都已发现这类命令注入漏洞。例如,已发现下面URL中的HP Openview存在一个易受攻击的命令注入缺陷:

img285b

10.1.2 例2:通过ASP注入

以下面的C#代码为例,它是一个用于管理Web服务器的Web应用程序代码的一部分。该功能允许管理员查看被请求的目录的内容:

img285c

如果按设想的方式运行,这段脚本将把用户提交的Directory参数值插入到预先设定的命令中,执行命令并显示结果,如图10-3所示。

img286a

图10-3 一个列出目录内容的功能

和前面易受攻击的Perl脚本一样,攻击者可以使用shell元字符破坏开发者预先设定的命令,并注入他自己的命令。&字符用于将几个命令组合在一起。提交一个包含&字符的文件名和另外一个命令就可以执行该命令并显示其结果,如图10-4所示。

img286b

图10-4 一个成功的命令注入攻击