0x01 前言

前段时间写了篇关于Dubbo在默认dubbo协议下,使用hessian2序列化方式的利用讲解文章《dubbo源码浅析:默认反序列化利用之hessian2》,我发现网络上并没有存在过讲解这方面利用的文章,其实这么简单,想必很多大佬在这之前已经知道了...

文章发了之后,我觉得应该很多公司都对其Dubbo服务的安全隐患进行了排查,对于一些没有安全审查能力的公司,可能会留下了比较大的安全隐患,故而,我又写了篇关于Hessian2反序列化安全加固的文章《dubbo反序列化问题-Hessian2安全加固和修复》 ,原理也非常之简单,其实就是加入黑名单,相对于原生Java反序列化原理差不多,只不过原生Java反序列化已经有实现了,只要配置系统环境变量java.serialization去配置Filter就好了。

前面,所讲解的都是Dubbo服务端的攻击手法,那么,我们有没有办法去攻击Dubbo客户端呢?既然Dubbo服务端能接收客户端发来的序列化数据进行反序列化,造成RCE,那么对于服务端的恶意序列化数据响应,必然也会造成客户端反序列化RCE吧?

带着这些疑问,我对其源码进行了一番研究,并且进行了实验。我们知道,使用Dubbo的时候,我们一般使用Zookeeper作为注册中心,也可以不使用注册中心,选择直连的方式,参考官方文档

若客户端选择了直连的方式,我们就可以类似Mysql Rouge、Redis Rouge的方式,去部署一个恶意的服务,在客户端连接上来后,返回恶意的序列化数据,造成客户端反序列化RCE。具体实现,后面我会在github开源的项目learn-java-bug放出,在dubbo这个module的com.threedr3am.bug.dubbo.rouge包下,具体使用方式,有两种反序列化攻击hessian2和原生java,具体选用随意,只要在攻击代码中修改一下以下代码即可:

String zookeeperUri = "127.0.0.1:2181";//直连模式下,无需关心这个配置
String rougeHost = "127.0.0.1";//当前恶意服务所在ip
int rougePort = 33336;//当前恶意服务通讯端口

new DNSURL().startRougeServer(zookeeperUri, rougeHost, rougePort, bytes, false);//直连模式下,startRougeServer方法最后一个attackRegister参数必须为false

上面只是直连的攻击手法,个人觉得比较low的,因为你没办法控制客户端的配置,既然都不可控,就谈不上直连攻击了。那么,有没有更容易的利用手法呢?我们能不能直接连接客户端,发送恶意序列化数据?

经过一番源码论证以及试验,也行不通,因为客户端默认也是使用netty,和服务端建立tcp长连接,也就是说,客户端不监听tcp连接,它只会主动建立连接,那么,这里是不是可以考虑tcp的攻击?是不是可以遍历seq,去伪造数据包?我这里不对其进行考虑和研究,当然是因为有更好的利用手法啦!


0x02 dubbo服务集群

为了避免单点故障,现在的应用通常至少会部署在两台服务器上。对于一些负载比较高的服务,会部署更多的服务器。这样,在同一环境下的服务提供者数量会大于1。对于服务消费者来说,同一环境下出现了多个服务提供者。这时会出现一个问题,服务消费者需要决定选择哪个服务提供者进行调用。另外服务调用失败时的处理措施也是需要考虑的,是重试呢,还是抛出异常,亦或是只打印异常等。为了处理这些问题,Dubbo 定义了集群接口 Cluster 以及 Cluster Invoker。集群 Cluster 用途是将多个服务提供者合并为一个 Cluster Invoker,并将这个 Invoker 暴露给服务消费者。这样一来,服务消费者只需通过这个 Invoker 进行远程调用即可,至于具体调用哪个服务提供者,以及调用失败后如何处理等问题,现在都交给集群模块去处理。集群模块是服务提供者和服务消费者的中间层,为服务消费者屏蔽了服务提供者的情况,这样服务消费者就可以专心处理远程调用相关事宜。比如发请求,接受服务提供者返回的数据等。这就是集群的作用。

上面是抄摘Dubbo官方文档的一番描述,Dubbo是一个具备高可用特性的RPC框架,为了高可用的特性,若单点部署,出现故障就跟高可用毛线关系没有了,所以,一般很多企业都会对其进行生产可用性的调整,无非就是集群部署,部署多个节点,那么,这个时候,若是使用注册中心的方式,就能达到动态的扩容和下线了,因为集群服务的每一台机器,都把自己的一些连接和配置信息放在了Zookeeper(其它的注册中心也一样,类似nacos等等)上了。

既然是通过Zookeeper去注册新的服务,让客户端去发现,进行连接使用。那么,这就是一个利用突破点,若我们把前面所说的,我们的dubbo rouge恶意服务注册到Zookeeper,这样,在客户端进行负载均衡的时候,就会有几率连接到我们的恶意服务,从而使dubbo客户端能接收并反序列化我们的恶意序列化数据,最终RCE,更绝的是,我们可以把其它机器的注册信息删除了,那么客户端就剩下我们的恶意服务可以连接了,一打一个准。


0x03 恶意服务注册

上一小节说了,把我们的恶意服务注册到Zookeeper来,经过一番调试,可以看到,默认情况下,以某service服务的全限定名com.threedr3am.learn.server.boot.DemoService为例,存在Zookeeper的路径为:

/dubbo/com.threedr3am.learn.server.boot.DemoService}/providers/

对于每一个dubbo服务,都会在providers目录下,新建一个children path,一个进行了URLEncode的path,例:

```

点击收藏 | 3 关注 | 2
  • 动动手指,沙发就是你的了!
登录 后跟帖