框架介绍
Apache Dubbo是一款高性能、轻量级的开源Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。Dubbo一开始把自己定位为一个RPC框架,专注于服务之间的调用。随着微服务的概念越来越火爆,Dubbo开始重新思考自己的定位,除了服务调用,开始逐渐向服务治理、服务监控、服务网关等方向扩展,随着Dubbo生态圈的逐渐完善,Dubbo慢慢的演变为一个成熟的微服务框架。
漏洞描述
在此前的CVE-2021-30179漏洞就是利用了Dubbo泛化调用功能,用户可以向Dubbo服务端传入任意类,这就导致攻击者可以通过反序列化的方式,来触发特定Gadget,达到远程命令执行的目的。在CVE-2021-30179后续的补丁中,增加了黑名单来过滤恶意传入的类,而CVE-2023-23638就是对此防御方式的绕过。
利用范围
- Apache Dubbo 2.7.x <= 2.7.21
- Apache Dubbo 3.0.x <= 3.0.13
- Apache Dubbo 3.1.x <= 3.1.5
相关介绍
简单介绍一下Dubbo的泛化调用,泛化调用(客户端泛化调用)是指在调用方没有服务方提供的 API(SDK)的情况下,对服务方进行调用,并且可以正常拿到调用结果,使用场景是在调用方没有接口及模型类元,知道服务的接口的全限定类名和方法名的情况下,可以通过泛化调用调用对应接口, 比如:实现一个通用的服务测试框架。泛化调用是通过Dubbo的filter机制实现的。
具体的使用方式可以参考:https://cn.dubbo.apache.org/zh-cn/overview/tasks/develop/generic/
漏洞分析
环境POC
POC采用的是https://github.com/X1r0z/CVE-2023-23638
JDK版本:8u121
代码分析
漏洞产生的本质还是利用了Dubbo泛化调用功能,而Dubbo处理泛化调用的方式是通过filter机制实现的,核心类是org.apache.dubbo.rpc.filter.GenericFilter
invoke方法首先会对Invocation对象进行校验
检查方法名是否为$invoke或者$invokeAsync、检查参数是否不为null、检查参数长度是否为3、检查invoke对象接口是否不是通过GenericService继承的,校验通过后就会通过getArguments() 获取参数,三个参数name、types、args分别为 String 类型、String 数组类型和Object 数组类型。
随后通过 findMethodByMethodSignature 反射查找服务端提供的方法,如果没有找到就会抛出异常,所以在POC中传入的方法必须是Dubbo服务端提供的方法。
随后通过获取请求中传递的generic的值来选择将参数反序列化为pojo对象的方式,一共有五种:
true、raw.return、nativejava、bean、protobuf-json。
CVE-2021-30179的利用方式
1. 将generic设置为raw.return
将最终调用PojoUtils#realize0
若pojo为map实例,则获取key为”class”的值,并通过反射得到class所对应的类type,后续处理中经过判断:如果type不是Map的子类、不为Object.class且不是接口,则进入else,对type通过反射进行了实例化,得到对象dest。