背景
近日,Apache Dubbo披露了Provider默认反序列化远程代码执行漏洞(CVE-2020-1948),攻击者可构造恶意请求,从而执行任意代码。具体信息如上图所示。
在官方邮件中,漏洞报告者还提供了官方的PoC脚本,感兴趣的读者可以自行抓包和学习。本文旨在复现漏洞,找出漏洞利用条件,提出漏洞修复方案。
简 介
是一款高性能、轻量级的开源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分析
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)
③ 触发命令执行分析在1中总结了常规的触发条件,可以根据这个条件来编写如下EXP,为了进一步说明1中的常规触发条件跟踪调试一下该EXP,调用栈如下:
1. hessian2在处理map反序列化时调用了 MapDeserializer.java 的 readMap() 方法Dubbo
2. 在 readMap() 方法中又调用了hashMap的 put() 方法
3. 在 put() 方法中调用 hash(key) ,该函数会计算对象的hash,即调用了 EqualBean 的 hashCode() 方法。而此方法又会调用obj的 toString() 方法,即调用了 ToStringBean 中 的 toString() 方法。
4. 在 toString() 方法中又调用了 beanClass 的全部getter方法,即调用了 JdbcRowSetImpl 中全部的getter方法。
5. 调用 JdbcRowSetImpl 中的 getDatabaseMetaData() 方法,进而调用 connect() 方法。
以上即是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 进行修改。
4. 编写恶意Java代码,这里使用百年不变的弹计算器来演示。
5. 编译恶意代码生成class文件,需要使用被攻击的目标Dubbo同样JDK版本进行编译。
6. 启动http服务,此时应该启动http服务的目录应为恶意class文件所在的目录
7. 启动ldap服务,这里为了方便使用 marshalsec
这里有几个点需要注意:
1. 8000为启动的HTTP服务监听的端口
2. EvilObject为恶意class文件的名称
3. 7777为ldap服务的监听端口,应与exp文件中的端口对应
8. 运行恶意消费者,然后弹计算器成功
到此为止,复现了漏洞利用过程。有兴趣的可以使用发现者提供的PoC去体验一波,这里就不过多展开了,发现者的分析为链接6。
● ○
整个漏洞利用流程是很典型的反序列化利用流程,利用该类漏洞的难点在于找到gadgets chain。在上述复现过程中,我们构造了完整的服务消费者和服务提供者。根据漏洞报告者的文章,官方Exp如下所示:
在复现过程中,我们通过注册中心获取service信息并用来进行攻击,所以我们实际上是利用了hessian 协议的漏洞,因为该序列化协议自身并没有针对rometools的gadgets的防护。而dubbo出现此次漏洞的原因,根据官方修复可以推断出是现在的版本没有对进入的service方法进行签名之类的验证,所以不用获取注册中心权限以掌握service信息就可以实施攻击。
➤ 漏洞修复建议
升级到dubbo最新版本,但官方提供的修复只是增加反序列化前的service name的判断,如果能控制中间注册中心还是会存在攻击风险。
对hessian协议进行扩展,主流方法就是增加对应的黑名单过滤器,维护一个黑名单,过滤可以触发gadget的类,如下图所示,详情可参照sofa-hessian(链接7)的处理。
编辑: 陈峰卫 审校: 李 东
参考链接 ● ○
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!
团队简介:
民生科技公司智能云技术部应用安全组,主要负责公司自营业务相关的安全规划、安全建设,保障项目的安全开发和系统的安全运营。
目前团队成员包括:李东,陈峰卫,安战超