Pwn a CTF Platform with Java JRMP Gadget
打CTF打腻觉得没啥新鲜感吗?来试试打掉整个CTF计分板吧!
前几个月,刚好看到某个大型CTF比赛开放注册,但不允许台湾参加有点难过 :( 看着官网最下面发现是FlappyPig所主办,又附上GitHub源代码,秉持着练习Java code review的精神就git clone下来找洞了!
(以下测试皆在FlappyPig的允许下友情测试,漏洞回报官方后也经过同意发文)
在有源代码的状况下进行Java的code review,第一件事当然是去了解第三方Libraries的相依性。关于Java的生态系统我也在几年前的文章小小分享过,当有个底层函数库出现问题时是整个上层的应用皆受影响!
从pom.xml观察发现用了:
- Spring Framework 4.2.4:从版本来看似乎很棒没什么重大问题
- Mybatis 3.3.1:一个Java ORM,似乎也没看到用法有问题
- Jackson 2.7.1:出过反序列化漏洞,不过enableDefaultTyping没启用,也无直接收取JSON输入无法触发漏洞
- Apache Shiro 1.2.4:【漏洞分析】Shiro RememberMe 1.2.4反序列化导致的命令执行漏洞。hmmm,真好连版本都是对的,不过当然没有这么简单XD
既然有现成的洞,当下即开始针对Shiro进行研究。首先遇到的第一个问题是照着文章内PoC的方式解密会发现失败,看来是有自己修改过的怎么办QQ?不过翻着翻着源代码在src/main/resources/spring-shiro.xml看到:
真开心XD
把AES Key更正后解回来的东西有AC ED开头看起来是序列化过后的资料,真棒:
|
|
接着就是产Gadget丢到远程服务器拿shell,但在这步怎么也无法成功利用,有点残念只好再继续研究下去!
当时的猜想是:Apache Shiro是一套实现身份验证的Library,而实现的方式可能有定义自己的ClassLoader因此导致现有的Gadget无法使用。
(尚无查证,不过在拿到shell后看到这篇文章Exploiting JVM deserialization vulns despite a broken class loader证明猜想也许是对的,不过这篇也没实现RCE XD)
虽然无法跳至Common Collection但至少还有JRE本身的Gadget可以跳去做二次利用!
纵观ysoserial除了JRE本身的洞外可利用的Gadget所剩无几,先来试试URLDNS至少先确认漏洞存在再说!
|
|
发现DNS有回显至少确认漏洞存在了,再继续往下利用!下一步我选的Gadget则是JRMPClient,由于JRMP是位于RMI底下的一层实现,所以走的也是反序列化的协议,“纯猜测”也许在这里使用ClassLoader就不会是Apache Shiro而是原本的ClassLoader。
(未查证,如有人可以帮忙查证请告诉我结果XD)
但这里又遇到一个问题是如何实现一个JRMP Server去接送过来的Protocol?网络上并没有人提供JRMPClient要如何使用的教学及利用方式!本来想要手刻但找着找着资料找回ysoserial上的JRMPListener.java,读了一下源代码才惊觉ysoserial真棒,各种模块化及利用都帮你写好了!
ysoserial分为两个部分,payload以及exploit,平常都只有用到产payload的部分而已,但实际上作者有写好几份可直接利用的exploit并模块化,让我们可以直接利用!
所以最后的利用则是:
|
|
如此一来就可以获得shell惹!
2018/03/27 01:23, Update
经过比较详细的分析,一开始失败的详细原因真是如同文章所说Shiro自己实现了一个Buggy的ClassLoader。所以payload当中出现ChainedTransformer或是InvokerTransformer都会出现Unable to deserialize argument byte array错误。而内置的URLDNS及JRMPClient刚好没用到上述方式实现Gadget所以可以使用!所以理论上透过RMI或是JDNI的方式应该也可以成功!
2018/03/27 10:09, Update
留言中有人给出了更详细的root cause! - “Shiro resovleClass使用的是ClassLoader.loadClass()而非Class.forName(),而ClassLoader.loadClass不支持装载数组类型的class。” 感谢帮忙解惑 <(_ _)>