CVE-2021-25641 — “0xDABB of Doom” 序列化 ID 篡改
漏洞概述
CVE 编号:CVE-2021-25641
CVSS 评分:9.8(Critical)
影响版本:Dubbo 2.7.0 ~ 2.7.8, 2.6.0 ~ 2.6.9
修复版本:2.7.9, 2.6.10
别名:”The 0xDABB of Doom”(Checkmarx 命名)
攻击类型:二进制协议级别的攻击,篡改协议头绕过安全机制
漏洞原理
背景
经过 CVE-2020-1948 和 CVE-2020-11995 的修复
Dubbo 2.7.8 的 Hessian2 反序列化已经有了黑白名单保护
但是! 其他序列化方式(Java 原生、Kryo、FST)没有这些保护
核心发现
Dubbo 协议 header 的第 3 字节(Flags)中,低 5 位是 Serialization ID
这 5 位决定服务端使用哪个反序列化器
早期版本中,服务端信任客户端发送的 Serialization ID
攻击者可以篡改这 5 位,强制服务端使用没有安全保护的反序列化器
篡改过程图解
1 | 正常请求 Header: |
攻击流程
1 | 1. 攻击者构造恶意 Java 原生序列化 payload(用 ysoserial) |
为什么之前的修复无效?
Dubbo 2.7.7/2.7.8 的安全检查只加在了 Hessian2 反序列化器中
Java 原生、Kryo、FST 反序列化器没有加任何检查
攻击者通过切换反序列化器就能绕过所有保护
复现步骤
环境搭建
1 | cd environments/cve-2021-25641 |
Python PoC 核心逻辑
1 | import socket, struct, subprocess |
使用 PoC 脚本
1 | python exploits/cve_2021_25641_bypass.py \ |
补丁分析
Dubbo 2.7.9 修复
核心修复:服务端不再信任客户端指定的 Serialization ID
服务端使用自己配置的序列化方式,忽略客户端 header 中的值
修复逻辑
1 | // 修复前: |
修复评价
这是一个正确方向的修复
安全原则:永远不要信任客户端输入
序列化方式应该由服务端决定,不应该被客户端控制
关联的 Gadget Chain
篡改为 Java 原生序列化后,所有 ysoserial 链均可使用:
CommonsCollections 全系列、CommonsBeanutils、ROME、Spring 等
篡改为 Kryo/FST 后,可使用对应格式的 gadget chain
思考与延伸
这是一个非常精妙的攻击思路
不是绕过反序列化检查本身
而是绕过”使用哪个反序列化器”这个选择过程
让有保护的反序列化器变成没保护的
二进制协议的安全设计教训
客户端可控的协议字段都可能被攻击者篡改
安全关键的配置(如序列化方式)应该由服务端决定
这个思路也适用于其他二进制协议的安全审计
| 上一章 | 目录 | 下一章 |
|---|---|---|
| 07-CVE-2020-11995 | Dubbo漏洞 | 09-CVE-2021-30179 |