目录遍历

在本节中,我们将讲解什么是目录遍历,描述如何进行路径遍历攻击和绕过常见的障碍,并阐述如何防范路径遍历漏洞。

Labs

如果你已经熟悉目录遍历背后的基本概念,并且只是想在一些现实、故意易受攻击的目标上练习利用它们,你可以从下面的链接访问这个主题中的所有实验。

查看所有目录遍历实验

什么是目录遍历?

目录遍历(也被称为文件路径遍历)是一种Web安全漏洞,它允许攻击者读取正在运行应用程序的服务器上的任意文件。这可能包括应用程序代码和数据、后端系统的凭证,以及敏感的操作系统文件。在某些情况下,攻击者可能能够写入服务器上的任意文件,从而允许他们修改应用程序数据或行为,并最终完全控制服务器。

通过目录遍历读取任意文件

考虑一个显示待出售商品图片的购物应用程序。 图片是通过如下HTML加载的:

<img src="/loadImage?filename=218.png">

loadImage URL接收一个filename参数并返回指定文件的内容。图片文件本身存储在磁盘上的/var/www/images/位置。为了返回图片,应用程序将请求的文件名追加到这个基本目录,并使用文件系统API读取文件的内容。在上述情况下,应用程序从以下文件路径读取:

/var/www/images/218.png

该应用程序没有针对目录遍历攻击采取任何防御措施,因此攻击者可以请求以下URL从服务器的文件系统检索任意文件:

https://insecure-website.com/loadImage?filename=../../../etc/passwd

这会导致应用程序从以下文件路径读取:

/var/www/images/../../../etc/passwd

序列../在文件路径中是有效的,意味着在目录结构中向上一级。连续的三个../序列从/var/www/images/向上至文件系统的根目录,因此实际读取的文件是:

/etc/passwd

在基于Unix的操作系统上,这是一个标准文件,包含在服务器上注册的用户的详细信息。

在Windows系统中,../..\都是有效的目录遍历序列,获取标准操作系统文件的等效攻击是:

https://insecure-website.com/loadImage?filename=..\..\..\windows\win.ini

LAB

文件路径遍历,简单案例

利用文件路径遍历漏洞的常见障碍

许多将用户输入放入文件路径的应用程序,都实现了某种防御路径遍历攻击的措施,而这些措施通常可以被绕过。

如果应用程序从用户提供的文件名中清理或阻止目录遍历序列,那么就有可能使用各种技术绕过这种防御。

你也许可以使用从文件系统根目录开始的绝对路径,例如filename=/etc/passwd,直接引用一个文件,而不使用任何遍历序列。

LAB

文件路径遍历,绝对路径绕过阻止遍历序列

你也许可以使用嵌套的遍历序列,例如....//....\/,当内部序列被清理时,它们将恢复为简单的遍历序列。

LAB

文件路径遍历,非递归清理遍历序列

在某些情况下,例如在URL路径中或者multipart/form-data请求的filename参数中,Web服务器可能会在将你的输入传递给应用程序之前清理任何目录遍历序列。有时可以通过URL编码,甚至双重URL编码../字符,转换为%2e%2e%2f%252e%252e%252f,来绕过这种类型的清除。各种非标准编码,例如..%c0%af..%ef%bc%8f,也可能有效。

对于Burp Suite Professional用户,Burp Intruder提供了一个预定义的有效载荷列表(Fuzzing - path traversal),其中包含你可以尝试的各种编码路径遍历序列。

LAB

文件路径遍历,多余的URL解码清理遍历序列

如果应用程序要求用户提供的文件名必须以预期的基本文件夹开始,例如/var/www/images,那么也许可以在包含必需的基本文件夹后面跟上适当的遍历序列。例如:

filename=/var/www/images/../../../etc/passwd

LAB

文件路径遍历,验证路径的开头

如果应用程序要求用户提供的文件名必须以预期的文件扩展名结束,例如.png,那么也许可以使用空字节来有效地在必需的扩展名之前终止文件路径。例如:

filename=../../../etc/passwd%00.png

LAB

文件路径遍历,空字节绕过文件扩展名验证

如何防范目录遍历攻击

防范文件路径遍历漏洞最有效方法是避免将用户提供的输入完全传递给文件系统API。许多做此类操作的应用程序函数可以被重写,以更安全的方式实现相同的行为。

如果认为无法避免将用户提供的输入传递给文件系统API,则应使用两层防御一起来防范攻击:

  • 应用程序在处理输入之前应验证用户输入。理想情况下,验证应该与允许值的白名单进行比较。如果所需的功能无法实现,那么验证应该确认输入只包含允许的内容,例如纯粹的字母数字字符。

  • 在验证了所提供的输入后,应用程序应将输入追加到基本目录,并使用平台文件系统API来规范化路径。它应验证规范化的路径是否以预期的基本目录开始。

下面是一些简单的Java代码示例,根据用户的输入来验证一个文件的规范路径:

File file = new File(BASE_DIRECTORY, userInput);
if (file.getCanonicalPath().startsWith(BASE_DIRECTORY)) {
    // process file
}

阅读更多

使用Burp Suite的Web漏洞扫描器发现目录穿越漏洞

Last updated