转载

Apache Dubbo Provider默认反序列化远程代

Apache Dubbo Provider默认反序列化远程代

Apache Dubbo Provider默认反序列化远程代

背景

近日,Apache Dubbo披露了Provider默认反序列化远程代码执行漏洞(CVE-2020-1948),攻击者可构造恶意请求,从而执行任意代码。具体信息如上图所示。

在官方邮件中,漏洞报告者还提供了官方的PoC脚本,感兴趣的读者可以自行抓包和学习。本文旨在复现漏洞,找出漏洞利用条件,提出漏洞修复方案。

dubbo 基础知识

简 介

是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

  序列化协议          

既然是远程过程调用,那必然会使用到Java的序列化和反序列化。Dubbo支持多种序列化协议,包括:

1. dubbo 序列化 

2. hessian2 序列化 

3. json 序列化

4. Java 序列化

由于本文不是序列化相关文章,所以这里对这四种序列化方式不做过多解释,只着重科普一下hessian2 序列化协议。

➤  hessian2反序列化攻击利用分析 gadget分析

在marshalsec工具中,有4种针对该协议的gadgets:

1. SpringCompAdv 

2. Resin

3. ROME

4. XBean

在复现过程中,我们使用了rometools,所以这里只分析ROME,其他几种方式会陆续分析。 

➤   ROME分析

① 常规触发条件(EqualsBean/ToStringBean)

1.  创建一个 EqualBean 对象,设置其obj属性为一个 ToStringBean 的实例;将 ToStringBean 实例的beanClass,obj属性设置为 JdbcRowSetImpl。

2. 将最终的对象插入进一个集合中(此时会调用 hashCode() )。

3. 调用EqualBean的hashCode() 方法,触发EqualBean obj属性的 toString() 方法,这里即 ToStringBean 的 toString() 方法。

4. 此 toString() 方法会调用其beanClass字段中全部 getter 方法,这里即是JdbcRowSetImpl 。其中getDatabaseMetaData() 方法会调用 connect() 方法,即通过 lookup方式触发了RCE。注: JNDI注入参照参考链接5。

 

② 触发代码(参照链接3)

Apache Dubbo Provider默认反序列化远程代

③ 触发命令执行分析在1中总结了常规的触发条件,可以根据这个条件来编写如下EXP,为了进一步说明1中的常规触发条件跟踪调试一下该EXP,调用栈如下:

1. hessian2在处理map反序列化时调用了 MapDeserializer.java 的 readMap() 方法Dubbo

Apache Dubbo Provider默认反序列化远程代

2. 在 readMap() 方法中又调用了hashMap的 put() 方法

3. 在 put() 方法中调用 hash(key) ,该函数会计算对象的hash,即调用了 EqualBean 的 hashCode() 方法。而此方法又会调用obj的 toString() 方法,即调用了 ToStringBean 中   toString()  方法。

4. 在 toString() 方法中又调用了 beanClass 的全部getter方法,即调用了 JdbcRowSetImpl 中全部的getter方法。

Apache Dubbo Provider默认反序列化远程代

Apache Dubbo Provider默认反序列化远程代

5. 调用 JdbcRowSetImpl 中的 getDatabaseMetaData() 方法,进而调用 connect() 方法。

Apache Dubbo Provider默认反序列化远程代

以上即是ROME Gadget的利用链。

环境搭建

● ○

环境搭建主要有两种:

1. 如链接1所示,构建 Dubbo Provider 和恶意的 Dubbo Consumer 。

2. 如链接2所示,使用官方示例 dubbo-spring-boot-auto-configure-provider-sample 。这里为了方便,我使用的第一种环境搭建方式。

复现过程

● ○

复现步骤如下:

1. 下载文件。 其中 DubboModules 为服务提供方, dubboconsumer 为服务消费方,此项目使用JDK8,且为了能 够使用ldap来进行JNDI注入,也需要选取指定版本的JDK8,否则可能导致复现不成功。

2. 导入idea中,这一步直接打开项目即可,但有些可能会遇到 Spring 配置文件相关问题,就需要各位自己踩坑了。

3. 开启 zookeeper 服务,这一步各位自行谷歌解决,根据自己的配置对 provider.xml 进行修改。

Apache Dubbo Provider默认反序列化远程代

Apache Dubbo Provider默认反序列化远程代

4. 编写恶意Java代码,这里使用百年不变的弹计算器来演示。

Apache Dubbo Provider默认反序列化远程代

5. 编译恶意代码生成class文件,需要使用被攻击的目标Dubbo同样JDK版本进行编译。

Apache Dubbo Provider默认反序列化远程代

6. 启动http服务,此时应该启动http服务的目录应为恶意class文件所在的目录 

7. 启动ldap服务,这里为了方便使用 marshalsec

这里有几个点需要注意:

1. 8000为启动的HTTP服务监听的端口

2. EvilObject为恶意class文件的名称

3. 7777为ldap服务的监听端口,应与exp文件中的端口对应

8. 运行恶意消费者,然后弹计算器成功

Apache Dubbo Provider默认反序列化远程代

Apache Dubbo Provider默认反序列化远程代

到此为止,复现了漏洞利用过程。有兴趣的可以使用发现者提供的PoC去体验一波,这里就不过多展开了,发现者的分析为链接6。

漏洞利用与修复

● ○

➤ 漏洞利用总结

整个漏洞利用流程是很典型的反序列化利用流程,利用该类漏洞的难点在于找到gadgets chain。在上述复现过程中,我们构造了完整的服务消费者和服务提供者。根据漏洞报告者的文章,官方Exp如下所示:

Apache Dubbo Provider默认反序列化远程代

在复现过程中,我们通过注册中心获取service信息并用来进行攻击,所以我们实际上是利用了hessian 协议的漏洞,因为该序列化协议自身并没有针对rometools的gadgets的防护。而dubbo出现此次漏洞的原因,根据官方修复可以推断出是现在的版本没有对进入的service方法进行签名之类的验证,所以不用获取注册中心权限以掌握service信息就可以实施攻击。

➤  漏洞修复建议

  • 升级到dubbo最新版本,但官方提供的修复只是增加反序列化前的service name的判断,如果能控制中间注册中心还是会存在攻击风险。

  • 对hessian协议进行扩展,主流方法就是增加对应的黑名单过滤器,维护一个黑名单,过滤可以触发gadget的类,如下图所示,详情可参照sofa-hessian(链接7)的处理。

Apache Dubbo Provider默认反序列化远程代

Apache Dubbo Provider默认反序列化远程代

编辑: 陈峰卫 审校: 李 东

  参考链接  ● ○ 

1. https://gist.github.com/OneSourceCat/01277dceba635eefbc010af36d3704d7

2. https://www.mail-archive.com/dev@dubbo.apache.org/msg06544.html

3. https://blog.csdn.net/u011721501/java/article/details/79443598

4. https://www.jianshu.com/p/93c00a391e09

5. https://www.mi1k7ea.com/2019/09/15/%E6%B5%85%E6%9E%90JNDI%E6%B3%A8%E5%85% A5/

6. https://www.tuicool.com/articles/bYRveej

7. https://github.com/sofastack/sofa-hessian

Thanks!

团队简介:

民生科技公司智能云技术部应用安全组,主要负责公司自营业务相关的安全规划、安全建设,保障项目的安全开发和系统的安全运营。

目前团队成员包括:李东,陈峰卫,安战超

Apache Dubbo Provider默认反序列化远程代

原文  http://mp.weixin.qq.com/s?__biz=MzUyMDMwMTI1Nw==&mid=2247486450&idx=1&sn=217a634a2d9dc5e1a9b779c6186dc3c4
正文到此结束
Loading...