定义

路径遍历(又称目录遍历)漏洞允许攻击者读取运行应用程序的服务器上的任意文件,可能包括:

  • 应用程序代码与数据
  • 后端系统的凭证信息
  • 敏感的操作系统文件

在某些情况下,攻击者还可能向服务器的任意文件写入内容,进而修改应用程序数据或行为,最终完全控制服务器。

示例

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

网站中有这样一个链接,如果在 Linux 系统中,一般 218.png 储存在 /var/www/images/218.png

想要测试路径穿越,就用:https://insecure-website.com/loadImage?filename=../../../etc/passwd 来读取

如果是 Windows,改用:https://insecure-website.com/loadImage?filename=..\..\..\windows\win.ini 即可

绕过

  1. 过滤了相对路径,尝试用绝对路径
  2. 单词匹配删除,双写绕过 ....//
  3. 中间件识别后删除 编码绕过
    • URL 编码
    • 二次 URL 编码
    • 非标准编码:Unicode 编码、UTF-8 变形编码或字符集混淆
    • Burp 中有集成词典,直接 Intruder 中 Add from list Fuzzing
  4. 限定起始目录
    • 保留目录再穿越
    • filename=/var/www/images/../../../etc/passwd
  5. 限定文件尾
    • 尝试零截断绕过:filename=../../../etc/passwd%00.png

防护手段

禁止传参

从根本上,防止通过用户传递文件路径来进行文件读取

  1. 用 “标识符映射” 替代用户输入路径
    • 需求:用户需要访问/static/images/avatar.jpg
    • 不安全方式:接收用户输入的avatar.jpg,直接拼接为BASE_DIR + userInput
    • 安全方式:后台维护 “文件 ID - 文件路径” 的映射表(如1 → avatar.jpg2 → cover.png),用户仅输入1,后台通过 ID 查询真实路径,完全不拼接用户输入。
  2. 固定文件访问范围:对于文件下载、预览等场景,直接在代码中固定允许访问的文件列表,用户只能从预设选项中选择,而非自由输入路径。

双层验证

如果无法避免用户输入,建议用两层验证

第一层:用户输入验证(前置过滤)

在处理用户输入前,先对输入内容做严格校验,过滤危险字符或限制输入范围,减少恶意输入的可能性。核心有两种校验策略(优先级从高到低):

  1. 白名单校验(最优)

    • 逻辑:预先定义允许的输入值列表,仅接受在白名单内的输入,拒绝所有其他输入。
    • 示例:若业务仅允许用户访问report1.pdfreport2.pdfreport3.pdf,则白名单为["report1.pdf", "report2.pdf", "report3.pdf"],用户输入非此列表的内容直接拒绝。
    • 优势:白名单是 “最小权限原则” 的体现,能彻底杜绝未知的恶意输入。
  2. 内容合法性校验(次优)

    • 逻辑:若无法使用白名单(如文件名允许用户自定义),则校验输入仅包含安全的字符(如字母、数字、下划线等),拒绝包含特殊字符(如../\/:*)的输入。
    • 示例:验证输入是否匹配正则^[a-zA-Z0-9_]+$,仅允许字母、数字、下划线,直接过滤包含../的恶意输入。
    • 但是可能被各种编码绕过!

第二层:路径规范化与基目录校验(核心防护)

输入验证仅为第一道防线,必须结合路径校验才能确保安全,这是防御路径遍历的关键步骤,分为两个操作:

  1. 路径规范化(Canonicalization)

    • 概念:调用操作系统 / 语言的文件系统 API,将拼接后的路径转换为绝对路径、去除所有冗余的遍历序列(如.././)和符号链接,得到唯一的 “规范路径”。
    • 原因:攻击者可能通过../.././、符号链接(如 Linux 的ln -s)等构造复杂路径,直接拼接后无法判断真实访问位置,规范化后能得到路径的真实形态。
  2. 基目录校验

    • 逻辑:验证规范化后的路径是否以预设的基目录(BASE_DIRECTORY)为前缀。如果是,说明访问的文件在允许的范围内;如果不是,说明攻击者试图跳转到基目录外的位置,直接拒绝。
    • 核心:确保用户只能访问基目录内的文件,彻底杜绝 “越权访问服务器其他目录” 的可能。