Luke a Pro

Luke Sun

Developer & Marketer

🇺🇦
EN||

目录遍历 (Directory Traversal)

| , 2 minutes reading.

1. 定义

目录遍历 (Directory Traversal)(又称路径遍历)旨在访问存储在 Web 根文件夹之外的文件和目录。

通过操纵带有“点-点-斜杠 (../)”序列及其变体的文件引用变量,攻击者可以访问存储在文件系统上的任意文件和目录,包括应用源代码、配置文件以及关键系统文件。

2. 技术原理

如果应用接受文件名并将其拼接到路径中而未经过滤:

// 易受攻击的 Node.js 代码
app.get('/download', (req, res) => {
  const filePath = path.join(__dirname, 'public', req.query.file);
  res.sendFile(filePath);
});

正常请求:?file=report.pdf -> /app/public/report.pdf

攻击请求:?file=../../../../etc/passwd 文件系统会将 .. 解析为父目录。 结果:/app/public/../../../../etc/passwd -> /etc/passwd

3. 攻击流程

sequenceDiagram
    participant Attacker as 攻击者
    participant App as 应用
    participant FS as 文件系统

    Attacker->>App: GET /image?filename=../../../etc/shadow
    
    Note over App: 应用拼接路径:<br/>"/var/www/html/images/" + "../../../etc/shadow"
    
    App->>FS: 读取文件
    Note over FS: 路径被解析为 /etc/shadow
    
    FS-->>App: 返回文件内容 (包含密码哈希)
    App-->>Attacker: 200 OK (敏感数据泄露)

4. 真实案例:Grafana (2021)

目标: Grafana (可视化仪表盘)。 漏洞类别: 目录遍历 (CVE-2021-43798)。

漏洞描述: Grafana 的一个插件资产加载器存在缺陷,它接受插件 ID 和文件路径,但未能正确清洗文件路径。

攻击过程: 攻击者可以发送类似如下的请求: /public/plugins/alertlist/../../../../../../../../etc/passwd

由于应用盲目信任插件名称后的路径段,它会读取并返回宿主机服务器上的任何文件。 这是一个在野外被利用的 零日 (Zero-Day) 漏洞,在许多管理员还没来得及修补之前,攻击者就利用它窃取了包含数据库密码的配置文件。

5. 深度防御策略

A. 避免在文件路径中使用用户输入

最安全的方法是不让用户直接提供文件名。

  • 间接引用: 在数据库中使用 ID (1, 2, 3) 映射到具体的文件名,用户仅通过 ID 进行访问。

B. 路径规范化与前缀检查

如果必须使用用户输入,请在访问路径前使用编程语言原生的路径规范化功能。

  1. 解析 完整路径。
  2. 检查 解析后的路径是否以预期的目录开头。
// 安全的 Node.js 代码
const safeDir = path.resolve(__dirname, 'public');
const userPath = path.resolve(safeDir, req.query.file);

if (!userPath.startsWith(safeDir)) {
  throw new Error('拒绝访问!');
}
res.sendFile(userPath);

C. Chroot 监狱

在“监狱 (Jail)”或容器 (Docker) 中运行 Web 服务器进程。即使遍历攻击成功,攻击者也只能看到容器内部隔离的文件,而无法看到宿主机的 /etc/passwd

6. 参考资料