目录遍历攻击如何防范?

wen 开源项目 79

从原理到实战的深度解析

目录导读

  1. 什么是目录遍历攻击? – 理解攻击者的“偷窥”手法
  2. 攻击如何发生? – 常用技术与漏洞成因
  3. 为什么它如此危险? – 真实世界的影响案例
  4. 核心防范策略(问答精华) – 开发者与运维者必须掌握的技巧
  5. 进阶安全加固方案 – 从代码到基础设施的全链路防御
  6. 常见误区与避坑指南 – 你以为的安全可能并不安全
  7. 总结与行动清单 – 立即可以执行的步骤

什么是目录遍历攻击?

目录遍历攻击(Directory Traversal Attack),又称路径遍历攻击,是一种通过操纵文件路径变量来访问Web服务器上受限目录或文件的攻击手法,攻击者利用(向上级目录跳转)或绝对路径符号,突破应用预设的访问权限,读取服务器中的敏感文件,如/etc/passwd、数据库配置文件、源代码甚至系统密码哈希。

目录遍历攻击如何防范?

简单例子
一个正常的图片访问URL可能为:

https://example.com/image?file=cat.jpg

攻击者将其修改为:

https://example.com/image?file=../../etc/passwd

如果服务器未做过滤,则可能直接返回Linux系统的用户账户信息。


攻击如何发生?

1 常见技术手段

  • 路径拼接:利用、..\%2f(URL编码)、..%5c(Windows反斜杠编码)等变体
  • 绝对路径注入:直接使用/etc/shadow替代相对路径
  • 空字节截断:在老旧PHP系统中通过%00截断字符串(已基本被修复)
  • 双重编码绕过:如%252e%252e%252f绕过简单的黑名单过滤

2 漏洞产生根源

  • 直接拼接用户输入到文件路径,未做任何验证
  • 信任用户提供的文件名参数(如?file=?path=?template=
  • 使用不安全的函数:如PHP的include()file_get_contents()readfile(),Java的File(),Python的open()
  • 未进行路径规范化处理:未将路径解析为实际绝对路径后再校验

为什么它如此危险?

  • 数据泄露:数据库密码、API密钥、业务代码暴露
  • 服务器控制:结合文件上传漏洞可写入木马文件
  • 横向移动:内网敏感文件(如密钥、证书)被读取
  • 历史案例:2017年Equifax数据泄露事件中,目录遍历是攻击链的一环;2019年Citrix ADC产品因目录遍历漏洞导致内部网络沦陷

核心防范策略(问答精华)

Q1: 最简单的防御方法是什么?

A: 禁止直接使用用户输入拼接文件路径。
将用户请求映射为预定义的资源ID(如数字ID、哈希值),而非文件名。

// 危险
$file = $_GET['file'];
readfile('/var/data/' . $file);
// 安全
$allowed = [1 => 'report.pdf', 2 => 'photo.jpg'];
$id = (int)$_GET['id'];
if(array_key_exists($id, $allowed)) {
    readfile('/var/data/' . $allowed[$id]);
}

Q2: 如果必须允许用户指定文件名,该如何处理?

A: 采用白名单+路径规范化+严格边界检查三层机制:

  1. 白名单:仅允许特定目录和文件扩展名(如只允许.pdf.jpg
  2. 路径规范化:使用realpath()(PHP)、Path.GetFullPath()(C#)、os.path.realpath()(Python)将路径转为绝对路径
  3. 边界检查:确保最终路径以允许的基础目录开头
    import os

def safe_read(base_dir, user_path): full_path = os.path.realpath(os.path.join(base_dir, user_path)) if not full_path.startswith(os.path.realpath(base_dir)): raise Exception("Access denied") with open(full_path, 'rb') as f: return f.read()


> **Q3: 如何防御编码绕过攻击?**
**A:** 对输入进行**两次解码校验**:  
首先对用户输入进行URL解码、Unicode解码、十六进制解码等,然后再进行路径检查,注意:必须使用服务端内置的解码函数,避免手动解码导致绕过。
> **Q4: Windows系统与Linux系统有何不同?**
**A:**   
- **路径分隔符**:Windows同时接受`\`和`/`,Linux仅接受`/`
- **大小写敏感性**:Windows不区分大小写(`CONFIG.XML`可绕过`config.xml`检查)
- **特殊设备名**:Windows上`COM1`、`LPT1`、`CON`等可能引发意外  
**建议**:统一使用`/`并禁用反斜杠;对Windows路径进行大小写标准化后再比较
---
## 5. 进阶安全加固方案
### 5.1 Web服务器配置
- **Apache**:`<Directory>` 限制访问范围,禁用FollowSymLinks,启用AllowOverride None
- **Nginx**:`alias`指令配合`root`限制,使用`internal`指令仅允许内部重定向
```nginx
location /downloads/ {
    alias /var/www/private/;
    internal;  # 仅允许内部请求
}
  • IIS:配置请求过滤,禁止序列,设置doubleEscaping=false

2 代码层加固

  • 使用成熟的文件服务库:如Amazon S3预签名URL,或WebDAV中间件
  • 最小权限原则:Web应用运行账户仅赋予读取必要目录的权限
  • 输入长度校验:限制路径长度,阻断超长编码尝试
  • 日志审计:记录所有文件访问请求,特别是包含、%2e的异常请求

3 云原生环境

  • AWS:使用S3 Bucket Policy限制公开访问,通过CloudFront分发
  • Kubernetes:限制Pod的文件系统权限,使用SecurityContext
  • CDN:配合WAF规则拦截模式(如Cloudflare的“路径遍历”规则)

常见误区与避坑指南

误区 正确做法
只过滤 攻击者可用嵌套、绝对路径、编码变体等绕过
使用黑名单禁用某几个符号 黑名单永远无法穷尽所有编码组合,必须用白名单
在前端进行过滤 前端校验可被轻易绕过,所有防御必须在服务端完成
依赖操作系统权限控制 只要Web应用能读取某文件,攻击者就能通过应用读取它
认为“内部系统”不需要防护 内网同样面临内部威胁及横向移动攻击

真实案例教训:某公司使用Java的File对象且只校验了,攻击者用/etc/../etc/passwd成功绕过——因为/etc/../etc/在标准化后仍为/etc/,但黑名单未覆盖绝对路径中的向上跳转。


总结与行动清单

每日可执行步骤

  1. 检查所有文件处理代码:搜索file_get_contentsfopenrequire等函数,确认用户输入未被直接使用
  2. 启用Web服务器日志:记录所有异常路径访问
  3. 配置WAF规则:至少拦截、%2e%2e%2f%252e%252e%252f等常见模式
  4. 使用静态扫描工具:如SonarQube、Checkmarx识别代码中的路径注入风险

月度审计任务

  • 渗透测试:针对文件下载、图片加载、模板渲染等功能点进行手动路径遍历尝试
  • 权限审计:确认Web应用进程运行在最低权限账户下
  • 依赖更新:检查框架或组件是否有已知目录遍历漏洞

终极心法

永远不要信任用户输入的字符串,即使是经过“清理”的。
将用户输入视为一个不透明的“选择索引”,而不是可执行路径的一部分——这才是防御目录遍历攻击的哲学核心。


本文基于OWASP、NIST、SANS等权威安全机构的最佳实践撰写,综合多篇技术资料去伪存真,确保防御建议经过实战验证。

抱歉,评论功能暂时关闭!