目录遍历 (Directory Traversal)
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. 路径规范化与前缀检查
如果必须使用用户输入,请在访问路径前使用编程语言原生的路径规范化功能。
- 解析 完整路径。
- 检查 解析后的路径是否以预期的目录开头。
// 安全的 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。
