目录
什么是目录遍历?
漏洞原理
实验
0x00 基础目录遍历
0x01 绝对路径
0x02 双写../绕过
0x03 URL编码绕过
0x04 绝对路径配合../
0x05 截断文件后缀
防御
目录遍历(目录穿越)是一个Web安全漏洞,攻击者可以利用该漏洞读取运行应用程序的服务器上的任意文件。 这可能包括应用程序代码和数据,后端系统的登录信息以及敏感的操作系统文件。
在某些情况下,攻击者可能能够在服务器上写入任意文件,(如,FFFTP是一款小型的FTP客户端软件。FFFTP客户端没有正确地验证FTP服务器所返回的LIST命令响应中包含有目录遍历序列(斜线)的文件名,如果用户受骗从恶意的FTP服务器下载的目录包含有带有恶意文件名的文件的话,就可能导致向用户系统的任意位置写入文件)从而允许他们修改应用程序数据或行为,并最终完全控制服务器。
若web要显示一个商品的图像,有时候开发者会用通过HTML加载,如:
使用filename参数加载图像文件,图片文件位置可能映射在 /var/www/images/ 上,所以真实的路径是 /var/www/images/214.png
这就导致了攻击者可以读取服务器上的任意文件:
https://www.*****.com/loadImage?filename=../../../etc/passwd
filename的参数值与真实路径组合起来就是:
/var/www/images/../../../etc/passwd
其等价于:
/etc/passwd
在Unix操作系统上,../ 是一个标准的返回上一级路径的语法;
在Windows操作系统上, ../ 和 ..\ 都是返回上一级的语句。
查看商品的图片,可以看到是通过filename参数来确定图片的:
右键打开图片,同时抓包,可以修改filename参数值,利用 ../ 返回上一级来遍历任意文件:
filename=../../../etc/passwd
web网站有时候会采取目录遍历的防御措施,如过滤 ../ 上一级等关键字,然后简单的过滤通常会被绕过。有时候可以直接采用绝对路径,无须../返回上一级目录遍历:
filename=/etc/passwd
有时候,防御措施是直接将 ../ 替换为空,可以直接采用双写/复写直接绕过:
filename=....//....//....///etc/passwd
如果在....//中,将../替换为空,最后的路径就变成:
....// => ../
也可以采用URL编码来绕过服务器对 . 或者 / 的检测:
. => %2c
/ => %2f
% => %25 (双重URL编码)
先尝试编码 / ,失败:
全编码,失败:
双重编码,即将%编码,成功:
有些web在获取filename图片文件的时候,会首先判断是否以一个固定的路径开头:
那么就可以配合../来返回上一级遍历任意文件:
filename=/var/www/images/../../../etc/passwd
某些web对filename的文件类型作了限制,只有当后缀为图片时才解析
这时候就可以利用 %00 来截断:
总之,目录遍历漏洞不会仅限于一个绕过姿势,通常会配合多个姿势进行组合攻击。
防止文件路径遍历漏洞的最有效方法是避免将用户提供的输入完全传递给文件系统API。
如果认为不可避免的是将用户提供的输入传递给文件系统API,则应同时使用两层防御,以防止受到攻击:
- 应用程序应在处理之前验证用户输入。理想情况下,验证应与允许值的白名单进行比较。如果所需的功能无法做到这一点,则验证应验证输入内容仅包含允许的内容,例如纯字母数字字符。
- 验证提供的输入后,应用程序应将输入附加到基本目录,并使用平台文件系统API规范化路径。验证规范化路径以预期的基本目录开头。
以下是一些简单的Java代码示例,用于根据用户输入来验证文件的规范路径:
File file = new File(BASE_DIRECTORY, userInput);
if (file.getCanonicalPath().startsWith(BASE_DIRECTORY)) {
// process file
}