0x00 事发
昨天又看到Dubbo公布了几个新的CVE,其中有两个RCE(CVE-2021-30179和CVE-2021-30180),一个SSRF(CVE-2021-25640),其中看到CVE-2021-30179标题是“Pre-auth RCE via Java deserialization in the Generic filter”,忽视了deserialization这个关键字,看邮件内容以为是一个新的反射任意调用洞,感觉有点东西,所以稍微跟了下细节。
(邮件内容图)
0x01 代码触发点
仔细跟了下源码,发现,其实就是在org.apache.dubbo.rpc.filter.GenericFilter中,如果发现被调用service的方法传入的参数中,第一个参数为字节数组byte[]时,会把这个字节数组数据进行反序列化,其中可选的序列化方式有nativejava、bean、protobuf-json等。
跟java web一样,Dubbo中也存在着Filter这样的调用拦截扩展,主要处理一些在RPC调用中的扩展处理,比如trace打印日志,qps限流熔断等等,开发者还能实现自己的Filter,去定制实现自身需求。
参考:https://dubbo.apache.org/zh/docs/v2.7/dev/impls/filter/
但实际在GenericFilter执行之前,也就是RpcInvocation构造的时候,因为Dubbo是默认基于netty(可以自己扩展实现)实现数据交互的,一般接收到tcp的调用数据时,会先对其进行decode,把数据流转换成RpcInvocation对象,然后再进行实际方法的调用。
而在这个decode的过程中,就已经存在反序列化的代码执行了,就在:
1 | org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation#decode(org.apache.dubbo.remoting.Channel, java.io.InputStream) |
所以,在这个地方已经可以进行反序列化攻击了
不过这个地方的反序列化,受限于默认hessian或者已配置的序列化类型,具有一定的局限性。
而CVE-2021-30179的漏洞触发点,算是反序列化类型攻击面的扩展了,可以把序列化方式从默认的hessian(spring aop那条链jndi攻击受限jdk版本和外连条件)转移到nativejava序列化类型,降低了反序列化攻击的难度。