【Portswigger 学院】路径遍历

教程和靶场来源于 Burpsuite 的官网 Portswigge:Path traversal - PortSwigger

路径遍历(Path traversal)又称目录遍历(Directory traversal),允许攻击者通过应用程序读取或写入服务器上的任意文件,例如读取应用程序源代码和数据、凭证和操作系统文件,或写入应用程序所访问或控制的文件,改变应用程序的行为,甚至接管服务器。

原理

假设一个购物应用程序用下面的标签展示一个图片文件的内容:

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

通过 filename 参数指定读取 218.png 文件的内容,218.png 是一个文件的名称,既然是文件,那么就必然有一个目录,该文件所在的目录也许在代码中被定义为 /var/www/images/,那么实际读取就是 /var/www/images/218.png 文件的内容。

然而,fiilename 参数是用户可控的,如果这个参数没有做任何路径遍历的防御,那么攻击者可以将其篡改为 ../../../etc/passwd,此时读取的文件是 /var/www/images/../../../etc/passwd,即 /etc/passwd,这是包括一个 Linux 系统所有用户的文件。如此,攻击者便知道了该 Linux 服务器存在哪些用户。

不仅限于 Linux, Windows 可用 ../ 或 ..\ 来实现路径遍历,例如:

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

实验

实验说明:

 其中说到产品图片展示存在一个路径遍历漏洞,利用它读取 /etc/passwd 就能完成实验。

进入实验场景:

随便点进一个产品,F12 查看网页源代码,发现图片展示的内容是通过操纵一个 filename 参数来实现:

把这个值复制出来访问,并修改 filename 参数值为 ../../../../etc/passwd 就能读取到 /etc/passwd 文件的内容:

常见的路径遍历防御和绕过

根目录开头

应用程序过滤 ../ 或 ..\,并且如果 filename 是相对路径,那么就在前面追加一个目录路径,如果是绝对路径,那么就不追加。此时,可尝试篡改 filename 为 /etc/passwd,也就是直接以根目录 / 开头,或许应用程序就不再在 filename 前面追加已定义好的工作目录,而是直接读取 /etc/passwd。

嵌套路径遍历序列

应用程序可能只过滤一次 ../ 或 ..\ 序列,那么可尝试类似于 ....// 或  ....\/ 的嵌套序列。

在测试的过程中,可以输入一次 ../ 加文件名看看是否读取到不加 ../ 同样的内容,比如 /image?filename=../30.jpg:

读取到的文件内容与 /image?filename=30.jpg 一模一样,那说明应用程序存在对 ../ 的过滤。此时,尝试嵌套 ../ 序列,比如 /image?filename=....//....//....//etc/passwd:

经过 URL 编码的路径遍历序列

有时候,应用程序会过滤 ../ 或 ..\,那么可以尝试先用 URL 编码处理一次或两次,比如 ../ 一次 URL 编码后是 %2e%2e%2f,两次编码是 %252e%252e%252f。

burpsuite 提供了两个路径遍历的 FUZZ 字典:Fuzzing - path traversal  Fuzzing - path traversal(single )

每个路径都有一个 {file} 占位符,可以利用下面的 Payload processing 功能把它替换为空或者想访问的文件,比如 etc/passwd。另外,因为这两个字典的路径已经包含经过 URL 编码的,所以还要取消 burpsuite 对 payload 的 URL 编码默认处理:

下图是字典攻击的效果:

字典中每个路径的 {file} 都被替换成 etc/passwd,有双重编码 / 的,也有不经过编码处理的。利用这两个字典 FUZZ 路径遍历漏洞可以囊括大部分的 payload 了。

基础目录路径匹配

有些应用程序要求用户提供的参数的格式是“目录路径+文件名”,而目录路径必须是符合要求,比如必须是 /var/www/images,这种防御仍然可以用 ../ 或 ..\ 序列绕过。如图:

filename 的值是目录路径 /var/www/images/ 加文件名 20.jpg,如果想直接读取 /etc/passwd,应用程序不允许:

要求 filename 必须以 /var/www/images 开头。

利用 ../ 绕过:

空字节截断

有些应用程序要求 filename 必须以某种后缀名结尾,比如 .png,那么可尝试空字节截断,例如 filename=../../../etc/passwd%00.png。

防御

最安全的防御就是不使用用户提供的 filename 作为文件系统函数的参数,如果无法避免,下面是推荐的处理步骤:

  1. 验证用户输入的 filename 是否在白名单中。如果无法设置一个明确允许访问的文件路径白名单,就设置一个允许出现在 filename 参数值的字符白名单,至少不包括 . / \
  2. 验证完用户输入的 filename,在 filename 前面添加基础目录的路径,然后用函数规范化路径,最后验证规范化后的路径的基础目录是否满足预先的要求。

关于第二点,所谓规范化路径,就是去除 ../ 或 ..\ 序列,比如一个 filename 追加基础目录的路径后其值是 /var/www/images/../../../etc/passwd,规范化处理后得到的路径是 /etc/passwd。

得到规范化路径后,就验证它是否符合预先要求的基础目录,比如 /etc/passwd 就不符合预先要求的 /var/www/images,应当视这次请求为恶意请求,拒绝继续处理。

以下是防御路径遍历漏洞的示例代码:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值