01 背景
Oracle官方在修补老的Weblogic反序列化漏洞时,将已经在互联网上暴露的PoC都加入了黑名单,所以若是绕过他的黑名单限制就依旧可以触发命令执行。接下来我们简单分析一下本次漏洞的成因,具体的weblogic反序列化漏洞原理这里不做具体分析,之后可以分享一次专题。这里我们来看看InboundMsgAbbrev中resolveProxyClass的实现,resolveProxyClass是处理rmi接口类型的,只判断了java.rmi.registry.Registry,其实随便找一个rmi接口即可绕过。
其实核心部分就是JRMP(Java Remote Methodprotocol),在这个PoC中会序列化一个RemoteObjectInvocationHandler,它会利用UnicastRef建立到远端的tcp连接获取RMI registry,加载回来再利用readObject解析,从而造成反序列化远程代码执行。
02 PoC重构
由于互联网上公开的poc,是通过服务器向rmi远程服务器获取命令执行代码从而执行命令并通过t3协议的回报告诉我们是否存在漏洞。但是这样的poc有很明显存在不能控制权限的问题。rmi远程服务器的命令执行代码我们不可控,并且会暴露我们有漏洞的资产,所以我们必须把poc重构成无风险的,也就是将rmi远程服务器改成自己的。
但是我们也知道,java会将对象序列化成字节码,如何在字节码中找到我们需要修改的ip和端口成为了一个问题。以下是我们的解决方法以及可以提供反序列化漏洞的一些研究方案。
我们可以通过 SerializationDumper(https://github.com/NickstaDB/SerializationDumper)将字节码的strut解析成我们更容易理解的格式。
由此我们可以过滤大部分构造poc所需要的java对象,根据功能直接定位到java.rmi.server.RemoteObject的content值。
将其hex解码后复制到010Editor里
结合之前SerializationDumper解析的字节码的格式我们可以大胆猜测 104.251.228.50前的000E为ip长度,000E转成10进制就是14,所以我们可以知道该字段为ip长度,相应的IP之后的为端口号7001。
通过查阅oracle的标准文档(https://docs.oracle.com/javase/10/docs/specs/serialization/index.html)我们可以了解到java反序列化字节码为对象的流程以及字节码的一些struct构造。我们可以由SerializationDumper的源码看出字节码事实上是二进制结构体嵌套结构体的产物。
我们在这里只需要把poc的rmi远程服务器指向我们自己的服务器即可。
由于存在嵌套关系,所以外层长度也需要修改为修改后的长度。
剩下的就是在远程服务器上启用ysoserial.exploit.JRMPListener,JRMPListener会将含有恶意代码的payload响应至请求方,也就是从在漏洞的weblogicserver。
$ java -cp ysoserial-0.0.5-SNAPSHOT-all.jarysoserial.exploit.JRMPListener 8888 CommonsCollections1 calc
03 后记
本文主要提供了对java序列化后字节码的一种研究方案,便于大部分人理解序列化和反序列化的原理,也便于后续漏洞的分析,有问题和想法的同学欢迎和我们共同探讨交流。