Kryo 是一个快速序列化/反序列化工具,其使用了字节码生成机制。Kryo 序列化出来的结果,是其自定义的、独有的一种格式,不再是 JSON 或者其他现有的通用格式;而且,其序列化出来的结果是二进制的(即 byte[];而 JSON 本质上是字符串 String),序列化、反序列化时的速度也更快。
很多大型软件都使用了这个库:
其相对于其他反序列化类的特点是可以使用它来序列化或反序列化任何Java类型,而不需要实现Serializable。
Kryo序列化使用kryo.writeObject(output)方法,反序列化使用kryo.readObject(input)或
kryo.readClassAndObject(input),此外还支持替换策略StdInstantiatorStrategy,写个Demo:
可以看到Kryo的反序列化速度极快。
能搜索到的Kryo反序列化漏洞资料较少,只有marshalsec的pdf文件这样一段介绍:
翻译过来如下, Kryo有两种反序列化漏洞:Kryo原生和替换策略StdInstantiatorStrategy,其对应的gadgets也不同,此外还存在一些finalize的附加危害(后反序列化漏洞):
这里直接拿marshalsec的代码讲解漏洞原理及利用链,可以从github上直接下载工程文件到本地编译使用:
https://github.com/mbechler/marshalsec
工程目录结构较简单,marshalsec目录下的是模拟各种反序列化包的使用场景,如Kryo.java,可见其继承MarshallerBase并实现了SpringAbstractBeanFactoryPointcutAdvisor和CommonsBeanutils,后者就是我们可使用的gadget:
这里重点在unmarshal方法里对输入in进行readClassAndObject反序列化操作,main方法执行run方法,跟进这个run方法,来到其继承的类MarshallerBase,这里对参数args进行校验,分别是我们在jar包里使用的[-a] [-v] [-t]:
指定后最终在test方法里调用特定gadget进行攻击:
而测试类最终也是走到这里,调用对应的unmarshal方法,从而完成整个调用链:
SpringAbstractBeanFactoryPointcutAdvisor为例具体攻击链如下:
关键点在于Kryo将数据反序列化为对象时,在对Map类的数据进行操作时调用了HashMap.put()方法,而后调用DefaultBeanFactoryPointcutAdvisor的equals方法,跟进getAdice中的this.beanFactory.getBean,参数为this.adviceBeanName,其值为ldap://x.x.x.x:1389/obj(攻击者可控),getBean方法接着调用this.doGetSingleton方法, doGetSingleton中调用了JndiLocatorSupport.lookup方法,最终利用JNDI进行RCE。
另外需注意的是payload中将SimpleJndiBeanFactory中的logger设置为NoOpLog而不是使用原来的SLF4JLog,是因为Kryo需要序列化的类有一个无参数的构造函数,只有NoOpLog符合这一点。
CommonsBeanutils的调用链也类似,参照Xstream的调用链。
1)结合业务场景尽量使用kryo.readObject而不是kryo.readClassAndObject;
2)通用方法:反序列化类设置白名单。
这里聊一下上面提到的后反序列化,可以参考这篇:
https://www.contrastsecurity.com/security-influencers/serialization-must-die-act-1-kryo-serialization
或者这篇:
https://paper.seebug.org/1133/
研究了一下,比较有意思,之前关注点都集中在反序列化过程中的触发点而忽略了反序列化之后的攻击面,主要是tostring方法,如IDEA:
还有finalize方法,其作用一般是用来做序列化之后的资源回收,如org.jpedal.io.ObjectStore类中的finalize方法:
可见其调用了flush方法,接着根据imagesOnDiskAsBytes中包含的文件路径依次删除。 我们可以通过以下代码,强制其finalize:
从而实现删除任意文件的效果:
调用链如下:
除此之外还有关闭任意文件、内存损坏、绕过反序列化黑名单等思路,有兴趣可以继续研究。
1)从Kryo反序列化到TCTF:
https://github.com/Tom4t0/My-CTF-Challenges/tree/master/tctf2018_finals
2)从marshalsec到CVE:
研究一下Marshalsec各种pop链,或许可以获得一些刷CVE的新思路。