tql,简直就是直播挖洞啊
Dubbo多个远程代码执行漏洞
马上年底了,发现年初定的几个漏洞的KPI还没来得及完成,趁着最近有空赶紧突击一波,之前业务部门被爆过Dubbo的漏洞,干脆就把Dubbo拖过来挖一把。之前没用过Dubbo,既然要挖它就先大体了解了一下,毕竟know it and then hack it。Dubbo是个基于Java的RPC框架,可以实现Java过程的远程调用。话不多说,先本地搞个Demo跑起来看看,Dubbo版本就采用最新的2.7.8。
本地Demo
先从Git地址https://github.com/apache/dubbo-samples 上下载示例项目,里面有几十个示例,我们随意选取一个dubbo-samples-http,后续以该示例为基础进行Demo开发与漏洞调试。此处示例项目的导入、基本配置、启动、运行步骤不再赘述。
创建Provider
Provider可以理解为服务端,我们创建如下Provider:
public interface DemoService {
String sayHello(String name);
}
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}
}
该Provider只提供了一个sayHello方法,该方法接受一个string类型参数,启动Provider,如下图:
创建Consumer
Consumer可以理解为客户端,我们创建如下Consumer:
public class HttpConsumer {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/http-consumer.xml");
context.start();
DemoService demoService = (DemoService) context.getBean("demoService");
System.out.println(demoService.sayHello("rebeyond"));
}
运行Consumer,如下图:
Provider的输出:
可以看到Consumer成功调用了Provider端提供的sayhello方法,Demo运行成功。
历史漏洞
Demo搭建好以后我们对dubbo的大体工作流程就有了一个比较完整的轮廓了,接下来就是思考攻击面,简单头脑风暴了一下想到了几个关键词:RPC、反射、反序列化、远程代码执行、攻击客户端、攻击服务端。以史为镜,可以知兴替,头脑风暴之后,我们简单看下Dubbo之前爆过的几个高危漏洞,。
CVE-2019-17564
先来看一下漏洞描述:“Apache Dubbo支持多种协议,官方默认为 Dubbo 协议。当用户选择http协议进行通信时,Apache Dubbo 将接受来自消费者远程调用的POST请求并执行一个反序列化的操作。由于此步骤没有任何安全校验,因此可以造成反序列化执行任意代码。”
通过描述可以看出,这是一个简单粗暴的反序列化漏洞,当客户端和服务端的通信采用http协议时,服务端直接对POST过来的二进制数据流进行Java原生反序列化,因此可以根据项目依赖的一些第三方库来构造Gadgets实现RCE。
这个漏洞的修复方案也是比较简单直接,直接把POST请求体的handler由“Java原生反序列化”改为“JsonRpcServer”。
CVE-2020-1948
漏洞描述:“Dubbo 2.7.6或更低版本采用的默认反序列化方式存在代码执行漏洞,当 Dubbo 服务端暴露时(默认端口:20880),攻击者可以发送未经验证的服务名或方法名的RPC请求,同时配合附加恶意的参数负载。当恶意参数被反序列化时,它将执行恶意代码。经验证该反序列化漏洞需要服务端存在可以被利用的第三方库,而研究发现极大多数开发者都会使用的某些第三方库存在能够利用的攻击链,攻击者可以利用它们直接对 Dubbo 服务端进行恶意代码执行,影响广泛。”
可以看到,这也是一个反序列化漏洞。这个漏洞的修复方案主要是增加了一个getInvocationWithoutData方法,对恶意的inv对象进行了一个置空操作:
了解完上面这两个已知漏洞,接下来我们就开始挖新洞了:)
Dubbo Redis协议远程代码执行漏洞
上文提到,Apache Dubbo支持多种协议,列表如下:
不同的协议是不同的入口分支,我们选择redis协议跟一下,首先改造一下我们的Demo,改成redis协议的版本,Provider做如下修改,根据官网的文档,我们增加get和set方法:
public interface DemoService {
String sayHello(String name);
String get(String key);
String set(String key,Object value);
}
public class HttpProvider {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/http-provider.xml");