Apache Dubbo漏洞CVE-2020-1948分析

阅读量    142981 | 评论 3

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

作者:银河安全实验室

0x01 简述

Dubbo是阿里巴巴一种开源的RPC服务框架,常被用来做分布式服务远程对象的调用,日前Dubbo被发现有CVE-2020-1948的远程代码执行漏洞,官方针对这一漏洞发布了新版本Dubbo2.7.7,对源码分析发现修复方式并不能阻止CVE-2020-1948漏洞利用。

 

0x02 补丁分析

针对爆发漏洞时间节点的commit记录发现,官方对传入参数做了类型的校验,针对修复的commit记录,我们做了详细的分析。

2.1 时间线

Dubbo漏洞爆发的时间线如下图所示:

2.2 修复代码分析

对提交修复的commit代码分析发现在DecodeableRpcInvocation中增加了输入参数类型的校验。Commits记录截图如下图所示:

点开查看代码,在原有的基础上增加了参数类型的校验,补丁代码如下图所示:

这里的parameterTypes是限制为Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;,如下图所示;

本次poc传入的参数类型为Class<?>类型。类路径为Class<?>class com.rometools.rome.feed.impl.ToStringBean类,如果对参数检查是可以有效阻止漏洞的利用,然而修复错了地方。

从git的commit记录来看,官方的修复思路推测是想在异常抛出前利用参数类型的校验并拦截,防止引用的toString()方法造成代码执行。

但是拦截错了地方,通过对源码的单步调试发现,此处抛出的异常并不在漏洞触发的调用链上,具体的漏洞分析可见下文。

 

0x03 漏洞分析

CVE-2020-1948远程代码执行漏洞原理是远程方法被动态调用导致的代码执行。

下文将会对本次漏洞利用方式和触发原理进行分析,因为本次代码执行漏洞触发原理与Java的反射机制相关,下文将简单阐述Java的反射机制。

3.1 Java 反射机制

Java的反射机制是指在程序的运行状态中,程序对于任意一个类都能知道这个类的所有属性和方法;对于任意一个对象,都能调用它的任意一个属性和方法;这种动态的信息获取和调用机制被称为Java的反射机制。

Dubbo本次的漏洞触发原理就是toStringBean类内部动态调用外部传入对象的方法导致的代码执行。在研究漏洞的触发前,需要先简单了解为什么toStringBean类会在代码中动态调用外部对象的方法。

3.2 toStringBean类初探

ToStringBean类是一个可以被序列化的公共类,可以将对象的类型和方法转成字符串供调用。

在ToStringBean实现的toString方法中,会遍历传入对象的所有方法(Method对象),并且通过java实现的invoke方法动态调用传入对象的所有Method对象。

toString实现方法如下图所示:

3.3 漏洞触发点

漏洞触发点在com.rometools.rome.feed.impl.ToStringBean类的toString方法中,toString方法中的getter.invoke(obj, NO_PARAMS);语句,如下图所示:

上图是动态运行中的调试截图,可以从图中看出obj参数的值为JdbcRowSetImpl类的实例化对象,当此处for循环执行到JdbcRowSetImpl类中getDatabaseMetData函数时候,会调用函数内connect方法,导致执行JdbcRowSetImpl的执行链,导致代码执行。

3.4 ToStringBean的调用链跟踪

一个正常的dubbo的服务调用,当找不到注册的service的时候会抛出异常,抛出异常的截图如下图所示:

这个inv是DecodeableRpcInvocation的实例化对象。上述红箭头中的+ inv语法会默认调用inv实例化对象的toString()方法,DecodeableRpcInvocation的toString()方法实现在父类Rpcinvocation中,跟进查看Rpcinvocation.java中的toString方法,截图如下:

上图中的argements方法根据右边的变量调试信息显示,实际上就是ToStringBean类的实例化对象,其中该对象有两个参数,beanClass是Class<?>类型,obj是Object类型,此时的调用栈显示obj是JdbcRowSetImpl实例化对象,beanClass是Class.ForName(“com.sun.rowset.JdbcRowSetImpl”)对象。Array.toString(Object[] obj)方法,将会在底层调用String.valueOf(Objectobj),此时这个obj对象是带有恶意负载的argements对象,继续往下跟踪Array.toString将argements向下执行,Array.toString(Object[] obj)方法如下图所示:

上图中可以发现传入的对象最后会经过String.valueOf转变为字符串储存在b变量里,继续往下跟踪,在String.valueOf方法中,当传入对象为toStringBean的时候,会调用toStringBean对象的toString()方法,String.valueOf方法如下图所示:

当进入ToStringBean的toString()方法的时候,如之前漏洞触发点所陈述,携带有恶意负载的对象,将会被执行恶意代码。由此我们清楚的看到了调用链,如下:

throw new RemotingException ->RpcInvocation.toString()->Arrays.toString()->String.valueOf()->toStringBean.toString()->getter.invoke(obj,NO_PARAMS)

最终在ToStringBean的toString()方法中Invoke动态调用对象造成代码执行。

 

3.5 缓解措施

一、内网服务

1、服务器防火墙添加内网IP白名单策略。

2、限制服务器的公网权限。

3、Dubbo-RPC基于TCP实现,并且当前Poc基于LDAP实现JNDI,因此可以在防火墙封禁掉dubbo服务端口的恶意TCP数据包。

二、外网服务

1、漏洞被利用的类在rome-{version}.jar包中,公网服务可以考虑自查是否引用了rome-{version}.jar包,如果引用了可以考虑重写toString()方法,重新编译并加载到生产环境。

2、服务器防火墙添加IP白名单策略。

三、流量设备类监控

1、在流量检测设备上可以增加检测规则,通过分析发现流量中可能会包含以下危险类的关键字(如:org.apache.xbean.naming.context.ContextUtil.ReadOnlyBinding,org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor,com.rometools.rome.feed, com.caucho.naming.QName, com.rometools.rome.feed.impl.ToStringBean等)。

下图是复现过程中的流量抓包:

 

0x04 漏洞复现

用最新版本dubbo-2.7.7版本做漏洞复现,显示最新版本仍存在CVE-2020-1948漏洞。

引用dubbo-samples的http的例子,git地址为https://github.com/apache/dubbo-samples,加载之后需要修改配置,将只支持http协议的方式修改为dubbo-rpc协议,maven相关配置如下图所示:

启用服务之后,利用传统的jndi的利用方式,在公网启用ldap服务和http服务,http服务目录下放入我们需要加载的远程执行代码的class文件。

本文中漏洞复现选择在windows本机上弹出计算器。

截至目前官方给出的最新版本依然存在该风险,利用如下图所示:

4.2 利用方式详解

本次漏洞复现的利用方式采用了JNDI远程加载恶意类的方式。

本次选用的反射链是com.sun.rowset.JdbcRowSetImpl,jdk对于该链在较新的版本有限制,在做漏洞复现的过程中尽量使用低版本的jdk版本,如环境有限制需要配置特定的绕过策略。

本次dubbo的漏洞触发点与fastjson有所不同,fastjson使用该链造成代码执行是因为在setAutoCommit方法的时候,该方法中会使用this.connect()方法,connect()方法中可以使用jndi的方式加载恶意类造成代码执行。

本次dubbo的利用方式虽然也是在connect()方法中被使用jndi的方式加载恶意类,但是dubbo是动态调用了JdbcRowSetImpl的getDatabaseMetaData方法,造成了connect方法被执行。

getDatabaseMetaData方法源码如下图所示:

从上图可以看出getDatabaseMetaData对象中也调用了connect方法,connect方法中会加载dataSource指向的地址,被加载远程Reference对象,造成JNDI方式的远程代码执行。

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多