从XStream浅析反序列化Gadget挖掘思路
0x01 前言 Java语言中最常见的一类漏洞就是反序列化漏洞,在各种数据格式到Java对象的转化过程中,常常存在这类漏洞。常见的数据类型例如jdk提供的原生序列化数据、json、yaml、xml等等。针对这类漏洞存在一种特别的漏洞挖掘方式—Gadget挖掘,这种漏洞挖掘不需要去寻找特定的外部入口漏洞入口,入口往往是公开的,应用通过对传入的数据内容进行过滤和检查。XStream是一款针对XML和Java对象转换而开发的工具库,由于其本身的一些特点,成为了这类漏洞挖掘里一个很典型的例子,因此本文针对XStream进行Gadget挖掘分析。本文更多的是分享Gadget挖掘时的思路,进而可以在其他类型的序列化中进行类似的思考和尝试。 0x02 XStream简介 XStream是一个常用的Java对象和XML相互转换的Java库。 从java对象到XML: 从XML到Java对象: XStream在1.4.18版本以前是存在许多CVE的,核心原因在于的它使用类的黑名单进行防御,因此层出不穷的绕过,在1.4.18版本以后默认为白名单,用户需要自行根据需要使用的类进行配置,到这个版本XStream才没有继续爆出高危的反序列化漏洞。 值得一提的是,XStream中有CVE编号的利用链都是不依赖任何第三方库,纯利用JDK中的类进行利用,由此可见XStream对于反序列化的宽泛程度。 0x03 历史漏洞 简单介绍一下XStream反序列的特点。反序列化漏洞的本质是,基于可以利用的Java类:序列化数据流→Source→Gadget→Sink。 对于原生的Java反序列化来说,可以利用的Java类是任意实现了Serializable的类,入口是ObjectInputStream的readObject方法。 对于XStream来说,可以利用的Java是任意类,入口是XStream的fromXML方法。 以一个经典的CVE-2013-7285来说,poc如下,执行的sink是ProcessBuilder.start() XStream中有一系列的Converter,用于对不同的标签进行转化。 这里sorted-set标签对应的是TreeSetConverter,它的代码逻辑中会调用TreeMap的put方法,而TreeMap的put方法会调用方法的compare方法对传入Map的对象进行判断对象应该存放的位置 public V put(K key, V value) { ... // split comparator and comparable paths Comparator<? super K> cpr = comparator; if (cpr != null) { do { parent = t; cmp = cpr.compare(key, t.key); if (cmp < 0) t = t.left; else if (cmp > 0) t = t.right; else return t.setValue(value); } while (t !...