记录黑客技术中优秀的内容,传播黑客文化,分享黑客技术精华

Apache dubbo (CVE-2020-1948) 反序列化远程代码执行漏洞及其补丁绕过深度分析

2020-07-07 17:12

Apache Dubbo简介

  Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质上是个服务调用的东东,说白了就是个远程服务调用的分布式框架(告别Web Service模式中的WSdl,以服务者与消费者的方式在dubbo上注册) 其核心部分包含:
  • 远程通讯: 提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及“请求-响应”模式的信息交换方式。
  • 集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持。
  • 自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。
下图是来自Apache dubbo 官网的工作流程和原理 1
  • Provider
    • 暴露服务方称之为“服务提供者”
  • Consumer
    • 调用远程服务方称之为“服务消费者”
  • Registry
    • 服务注册与发现的中心目录服务称之为“服务注册中心”
  • Monitor
    • 统计服务的调用次调和调用时间的日志服务称之为“服务监控中心”
  • Container
    • 服务运行容器。
Provider将本地提供的远程方法在注册中心进行注册,Consumer需要调用时会先去注册中心进行查询,根据注册中心返回的结果再去对应的Provider中调用对应的远程方法,如果有变更,注册中心将基于长连接推送变更数据给Consumer 。 启动注册中心,Apache dubbo 推荐使用的注册中心时Apache ZooKeeper注册中心 下载地址https://zookeeper.apache.org/releases.html 启动ZooKeeper之前可以自定义修改 “/conf/zoo.cfg”配置文件里的 clientPort和dataDir的值。 2 Apache Dubbo有一个web端的管理界面 github地址如下https://github.com/apache/dubbo-admin 下载完成后进入/dubbo-admin-server/src/main/resources目录修改application.properties配置文件,将其中的注册中心地址修改为自己启动的注册中心的地址3 dubbo-admin-server 目录下运行 mvn package -Dmaven.test.skip=true 将该模块打包成jar包4 然后 java -jar dubbo-admin-server-0.2.0-SNAPSHOT.jar 启动dubbo-admin-server,此时启动了 dubbo管理的服务端但是没有UI界面。 进入到 dubbo-admin-ui 中 执行 npm install 该命令执行完成后 执行npm run dev 。 5 访问http://localhost:8081 此时就有了UI界面,默认账号密码都是root,在服务查询中 我们可以看到Provider在Zookeeper注册中心中注册的远程方法服务,目前没有注册所以无可用数据。 6 启动我们使用dubbo框架写的程序 7 可以看到我们的远程方法服务成功在zookeeper注册中心进行注册 8  

CVE-2020-1948 深度分析

首先观察一下网上已经公布的POC的代码 [crayon-5f043c6238119200336313/] 不难看出,该漏洞利用链最终是通过JdbcRowSetImpl调用jndi来进行远程代码执行。同时我们发现该gadget中用到了com.rometools.rome.feed.impl.ToStringBean,所以Provider的pom.xml中需要添加rometools的引用 [crayon-5f043c6238123976068507/] 通过wireshark抓包来看一下 POC发出的报文内容 9 我们将断点打在 org.apache.dubbo.remoting.transport.DecodeHandler 的第57行代码上。 10 跟进该方法后可以看到该方法内首先会进行一个if判断,判断完成后会调用DecodeableRpcInvocation.decode()方法并传递进去两个参数,其中有一个inputStream参数,我们详细看一下该参数的内容 11 12 可以看到正是我们通过POC发送的序列化数据 跟进该方法,在第131行代码处有一个if判断,这里通过RefctUtils.desc2classArray()处理完desc参数然后返回一个ToStringBean的类对象。 13 紧接着通过Hessian将ToStringBean的类对象反序列化成ToStringBean对象并赋值给args参数 14 仔细观察一下此时args指向的ToStringBean对象的详细内容,可见此时ToStringBean对象有两个属性已经被赋值为JdbcRowSetImpl。 15 当前方法执行完成后 args参数和pts参数分别被赋值给当前对象的arguments属性和parameterTypes属性,然后当前DecodeableRpcInvocation作为参数进行返回 返回到DecodeHandler中,在第51行代码中传入的message参数是一个Request对象,该Request对象是dubbo的包中的,简单看一下该对象的详细信息 16 17 跟进该方法,然后继续跟进handleRequest()方法。 18 在DubboProtocol类的第263行代码中经过一个if判断然后判断成功会抛出一个RemotingException,关键点就在这里,可以看到传入的参数中采用了字符串拼接的形式,当使用字符串拼接的时候,会自动调用StringBuilder的对象的append方法,依次处理channel.getRemoteAddress()的返回值,channel.getLocalAddress()的返回值,getInvocationWithoutData(inv)的返回值,而getInvocationWithoutData(inv)的返回值正式含有恶意请求的DecodeableRpcInvocation对象,StringBuilder要调用DecodeableRpcInvocation的toString方法将其转化为字符串 19 20 21 DecodeableRpcInvocation类的父类RpcInvocation重写了toString方法,看一下RpcInvocation.toString()方法的实现 22 同样还是字符串拼接,其中Arrays.toString(arguments),agruments正是之前封装进DecodeableRpcInvocation对象中的ToStringBean对象。接下来自然会调用ToStringBean.toString()方法。 ToStringBean.toString()方法,执行时取出其中的obj属性获取其类名称,并作为参数传入另一个重写的toString方法 23 该toString方法中会通过反射不断调用JdbcRowSetImpl对象的各个方法,当反射调用JdbcRowSetImpl对象的getDatabaseMetaData方法时,会触发JDNI远程访问dataSource 24 25 我们可以看到dataSource的值 26 27   至此Apache dubbo (CVE-2020-1948) 反序列化远程代码执行漏洞原理分析完毕  

补丁绕过分析

这次针对该漏洞的补丁非常简单,在分析该漏洞时说过在DecodeableRpcInvocation类的第131行有一个if 判断,以下是2.7.6版本中该判断的代码 13 更新后的2.7.7版本该判断的代码如下,可见在该判断內有增加了一个if 判断,且新增加的判断如果判断失败则会抛出IllegalArgumentException异常终止当前线程的执行。 28 那么如何绕过该判断让程序继续执行下去从而触发远程代码执行,我们跟入RpcUtils.isGenericCall()方法中来仔细观察。 29 不难发现该方法内用仅仅只用String.equals方法对比了method参数是否和$INVOKE常量或者$INVOKE_ASYNC常量的值相同。 我门看一下两个常量的值 30 我们此时 method的值为“test”可见并不相同,紧接着进入RpcUtils.isEcho()方法,同样是和常量进行对比,显然结果也不相同 31 32 所以if 判断内的最终结果为true,从而抛出异常终止执行。绕过的方法相比大家也都想到了,我们只要让method的值等于“$invoke”,“$invokeAsync”,“$echo”任意一个即可绕过。我们返回POC中查看与method对应的值是哪一个 33 一眼就能发现其中的method_name就是我们要找的,我们只需要修改‘test’为‘$invoke’即可对当前补丁进行绕过。

总结

此次漏洞是序列化传输到后台的数据被翻序列化完成后,在后续的处理过程中的一个异常处理中进行了危险操作,从而触发了gadget。  
知识来源: blog.topsec.com.cn/apache-dubbo-cve-2020-1948-%e5%8f%8d%e5%ba%8f%e5%88%97%e5%8c%96%e8%bf%9c%e7%a8%8b%e4%bb%a3%e7%a0%81%e6%89%a7%e8%a1%8c%e6%bc%8f%e6%b4%9e%e5%8f%8a%e5%85%b6%e8%a1%a5%e4%b8%81%e7

阅读:15999 | 评论:0 | 标签:CVE 漏洞

想收藏或者和大家分享这篇好文章→复制链接地址

“Apache dubbo (CVE-2020-1948) 反序列化远程代码执行漏洞及其补丁绕过深度分析”共有0条留言

发表评论

姓名:

邮箱:

网址:

验证码:

ADS

标签云