Java 7u21/8u20 反序列化漏洞
前言
非常特别的反序列化链,虽然可用范围很小,但是用到的类都在 JDK 内部。
7u21
观察到参考文章里面的修复方式是对 AnnotationInvocationHandler 类的 this.type 属性做了限制,所以找找用到这个属性的地方,找到 getMemberMethods 函数:
1 |
|
函数中会使用反射根据 type 属性获取某个 Class 中定义的函数,再找找调用了 getMemberMethods 函数的地方:
1 |
|
简单来说就是在参数为 type 的实例的时候,可以按顺序调用某个类/接口的函数,但是如果调用了有参函数就会抛出异常结束执行,所以选择类/接口的时候要注意其函数的顺序。
而我们的好朋友 TemplatesImpl 类继承了 Templates 接口,里面只有两个函数:
1 |
|
而这两个函数都可以出发我们熟悉的 TemplatesImpl 从字节码中定义、加载类的操作,所以可以用这种方式进行 RCE。
equalsImpl 这个名字明显与 equals 相关,调用代码在 invoke 中:
1 |
|
用 AnnotationInvocationHandler 代理 equals,就能触发上面的反射调用函数。而 readObject 中会触发 equals 的类也挺多的, 比如 HashSet、HashTable 等等。
maven 弄个适用于 JDK7 的低版本 javassist:
1 |
|
测试代码(使用 HashTable 需要注意一下保证 hashCode 一致):
1 |
|
8u20
在 AnnotationInvocationHandler 类中的修复如下:
1 |
|
在 readObject 函数中进行了限制,如果 type 属性不是注解类型,就会抛出异常直接中断反序列化进程。
但是对 Java 反序列化有一点了解的师傅都知道,异常是在 readObject 函数中抛出的,此时该对象的大部分数据已经完成了反序列化,剩下还没反序列化的就是 writeObject 函数中额外写入的函数(如 writeObject、writeInt 等)。
而 AnnotationInvocationHandler 类中并没有 writeObject 函数,也就是说此时 AnnotationInvocationHandler 对象其实已经反序列化完成了,只是被抛出的异常中断了流程。所以只要解决这个抛出的异常,我们就能绕过这个修复继续 RCE,而解决异常的方法一般来说就是 try/catch,比如在某个类的 readObject 函数中,有一块 try/catch 的代码块里面调用了 readObject 还原 writeObject 写入的额外数据。
但这样一来即使捕获了异常没有中断反序列化,反序列化出来的这个 AnnotationInvocationHandler 对象多半也会因为抛出了异常而不会保存下来,变成一个只存在于内存,无法访问的“幽灵”对象。
按照 payload 原作者的思路,要访问这个“幽灵”对象,就要用到一个 Java 反序列化的机制 REFERENCE,用 SerializationDumper 查看将一个对象写入两次生成的序列化数据:
1 |
|
因为同一个对象写入了两次,而为了反序列化的简便肯定不会将相同数据写入两次,所以第二次写入的时候写入的就不是对象,而是一个 REFERENCE 引用,指向前面的对象,反序列化的时候就能知道这里是个与前面相同的数据。
按照原作者的思路,这里构造 payload 要自行编写字节码(因为是流式数据,所以按顺序写下去就行了),构造难度不高,阅读一遍原作者的源码就能明白。
唯一有一个坑点的就是 AnnotationInvocationHandler 对象的 flag 字段,如果不加上代表 SC_WRITE_METHOD 的 1,在抛出异常后会导致后续的反序列化出错,理由不明(或许是因为没有实现 writeObject 函数的类,在 readObject 时不会有因为反序列化额外数据导致的异常,所以此时如果出现了异常就会直接中断反序列化)。
我自己写了个 Hashtable 的利用链来巩固一下:
1 |
|
最后再 patch 一下,将 templates 中属性 _name 的引用 handler 改成某个 String 即可。
理论上,传统构造方式应该也是可行的(给 AnnotationInvocationHandler 对象的 flag 加上 SC_WRITE_METHOD,再用 endorsed 修改一下 Proxy 等类,加上一个不存在的 Object 类型属性),但是比较麻烦就是了。
参考
https://mp.weixin.qq.com/s/Daipik5qK6cIuYl49G-n4Q