漏洞描述
Apache Dubbo是一款高性能Java RPC框架,核心功能是方便面向接口的远程过程调用,集群容错和负载均衡,以及服务自动注册与发现。
Apache Dubbo支持多种协议,官方默认为 Dubbo 协议。当用户选择http协议进行通信时,Apache Dubbo 将接受来自消费者远程调用的POST请求并执行一个反序列化的操作。由于此步骤没有任何安全校验,因此可以造成反序列化执行任意代码。
漏洞影响范围:
- 2.7.0 <= Apache Dubbo <= 2.7.4
- 2.6.0 <= Apache Dubbo <= 2.6.7
- Apache Dubbo = 2.5.x
环境搭建
复现环境:win10 + jdk1.8 + idea(搭建dubbo) + zookeeper 3.4.10
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,主要是用来解决分布式应用中经常遇到的一些数据管理问题。
首先先下载zookeeper的压缩包:https://archive.apache.org/dist/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz
然后在解压后的根目录下新建两个文件夹:data和logs,后面配置要用到。
接着修改 conf目录下的zoo_sample.cfg为zoo.cfg,
并添加如下内容,分别为刚刚新建的data和logs目录路径
双击bin目录下的 zkServer.cmd,启动,zookeeper会监听2181端口
zookeeper配置好后,开始搭建dubbo,这里以官方的domo为例:https://github.com/apache/dubbo-samples/tree/master/java/dubbo-samples-http
下载后修改dubbo-samples-http里面的pom.xml
先修改版本为2.7.3,然后添加依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
然后导入idea,maven下载依赖构建项目即可。(如果下载时间特别长,可以考虑更换源,方法参考:https://www.cnblogs.com/zaqzzz/p/12443794.html)
最后启动dubbosampleshttpHttpProvider服务,出现dubbo service started 就说明搭建完成了。
复现分析
首先要先通过反序列化工具ysoserial生成payload,保存到calc.ser文件
java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections4 "calc" > calc.ser
浏览器访问http://192.168.1.101:8080/org.apache.dubbo.samples.http.api.DemoService 并burp抓包该请求,首先先修改为post类型,接着在post的内容里导入我们刚刚生成的payload,不要直接复制,burp右键Paste from file添加payload
发包,成功弹出了计算器。
下面简单分析下该漏洞,从idea的报错调用栈可以看出,javax.servlet.http.HttpServlet.service应该就是入口
查看javax.servlet.http.HttpServlet.service,在有处理request请求的地方加个断点,如下
重新开启调试模式,burp再次发送攻击请求,来到断点处
跟入来到DispatcherServlet的service方法,通过请求中的端口去获取服务信息,如果没有则返回404 Service not found
下面继续跟入handle方法,由于我们传输的协议是http,所以就进到了HttpProtocol类中对应的handle方法。
然后先判断请求类型是不是为post,如果不是的话就直接返回500。
确定请求类型为post后,根据请求的内容生成HttpInvokerServiceExporter对象,最后再调用其handleRequest方法,跟入查看
这里发现是通过readRemoteInvocation 来处理我们的request请求,继续跟入
这里返回了readRemoteInvocation的结果,继续跟入
可以看到,这里先是获取了我们request请求的数据流,接着传入到了doReadRemoteInvocation方法,跟入查看
可以看到反序列化入口了,这里直接调用了Readobject,整个攻击请求的处理流程基本清晰了,这个漏洞其实并不复杂,修复的话可以直接升级到2.7.5以上,或者关闭http协议,其他的思路的话还可以考虑用jsonrpc的处理,而不是通过httpinvoker,这样的话就没办法处理我们的java序列化字节流从而抛出异常。
reference:
http://www.lmxspace.com/2020/02/16/Apache-Dubbo反序列化漏洞(CVE-2019-17564)