渗透测试步骤

(1)一些应用程序检查用户提交的文件是否以一种或一组特殊的文件类型结尾,并拒绝访问其他内容的请求。有时候,可以在请求的文件名后放入一个URL编码的空字节,在后面连接应用程序接受的文件类型,从而避开这种检查。例如:

img297c

这种攻击有时会成功,是因为应用程序使用API在托管执行环境下执行文件类型检查,该执行环境允许字符串包含空字符(如Java中的String.endsWith())。但是,当获取文件时,应用程序最终在一个无法控制的环境(其中的字符串以空白字符结束)中使用API,因此文件名被截短为想要的值。

(2)一些应用程序将它们自己的文件类型后缀附加在用户提交的文件名后,尝试控制被访问的文件类型。在这种情况下,基于相同的原因,前面的任何一种利用都可能取得成功。

(3)一些应用程序检查用户提交的文件名的开头部分是否为起始目录的某一个子目录,或者一个特殊的文件名。当然,通过以下方法可轻易避开这种检查:

img298a

(4)如果以上针对输入过滤的攻击都无法成功,可能应用程序实施了几种类型的过滤,因此需要同时使用上面的几种攻击方法(同时针对遍历序列过滤与文件类型或目录过滤)。遇到这种情况,如有可能,最好的办法是将问题分解成几个独立的阶段。例如,如果请求

img298b

能够成功,但请求

img298c

却导致失败,那么尝试使用所有可能的遍历序列,直到第二个请求获得成功。如果使用这些成功的遍历序列仍然无法访问/etc/passwd,就请求以下文件,检查应用程序是否实施任何文件类型过滤,以及是否可以避开这种过滤:

img298d

彻底检查应用程序定义的起始目录,设法了解它实施的全部过滤,看是否可以利用上述技巧避开每一种过滤。

(5)当然,如果能够随意访问应用程序,那么攻击就变得更加简单,因为渗透测试员可以系统性地攻击每种输入,并最终确定通过哪些文件名(如果有)可以到达文件系统。

img007  处理定制编码

我们曾经见到,应用程序采用的文件名编码方案最终以危险的方式进行处理,模糊处理也不能提供任何安全保障,这时就会出现最为可怕的路径遍历漏洞。

例如,一些应用程序具有某种工作流程功能,允许用户上传与下载文件。执行上传操作的请求提供一个文件名参数,它在写入文件时易于受到路径遍历攻击。如果一个文件成功上传,那么应用程序再为用户提供一个下载URL。这里有两点值得注意。

img002 应用程序核对将要写入的文件是否已经存在,如果存在,就拒绝重写这个文件。

img002 为下载用户文件而生成的URL使用一种定制模糊处理方案表示。这种方案似乎是一种定制的Base64编码形式,它在每个编码文件名位置使用一组不同的字符。

总的来说,这些注意点给直接利用漏洞设立了障碍。首先,尽管能够在服务器文件系统中写入任何文件,但攻击者却无法重写任何现有的文件,而且,Web服务器进程拥有的较低权限意味着攻击者不可能在任何有利位置创建新文件。其次,如果不对定制编码进行逆向工程,攻击者也不可能请求任意一个现有的文件(如/etc/passwd)。

一个简单的实验就可以证明模糊处理后的URL包含用户最初提交的文件名字符串,如下所示。

img298e

编码后的URL之间的长度差异表明,在应用编码之前,应用程序并未对其进行路径规范化。这种行为让攻击者有机会对漏洞加以利用。首先通过以下名称提交一个文件:

img299a

它的规范化形式为:

img299b

因此可以被Web服务器写入。上传这个文件将生成以下包含模糊处理文件名的下载URL:

img299c

要修改这个值以返回文件/etc/passwd,只需从右边将其截短成

img299d

果然,尝试使用这个值下载文件时,结果返回服务器的passwd文件。这说明,服务器为攻击者提供了足够的资源,即使不解译模糊处理算法,攻击者也可以使用它的编码方案编码任意文件路径。

img001  注解  细心的读者可能已经注意到,在上传的文件名中出现了一个多余的./。这样做是必要的,因为它可确保截短后的URL符合Base64编码规则,在3字节的明文边界结束,并因此在4字节的编码文本边界结束。在服务器上解码时,从一个编码块的中间截取URL几乎肯定会造成错误。

img007  利用遍历漏洞

确定一个可向服务器文件系统读取或写入任意文件的路径遍历漏洞后,渗透测试员应当实施哪种攻击利用这些漏洞呢?许多时候,在文件系统上拥有和Web服务器进程相同的读取/写入权限。