文章目录
- 写在前面
- 利用链
- JDK7U21原生反序列化利用链分析
- 流程跟踪
- 参考文章
写在前面
这段时间看了也跟踪了CC链,CB链,也跟踪调试了shiro的两个链子,XMLDecoder等,就用JDKK7U21原生反序列化利用链来暂时结束下最近的学习
利用链
LinkedHashSet.readObject()
LinkedHashSet.add()
...
TemplatesImpl.hashCode() (X)
LinkedHashSet.add()
...
Proxy(Templates).hashCode() (X)
AnnotationInvocationHandler.invoke() (X)
AnnotationInvocationHandler.hashCodeImpl() (X)
String.hashCode() (0)
AnnotationInvocationHandler.memberValueHashCode() (X)
TemplatesImpl.hashCode() (X)
Proxy(Templates).equals()
AnnotationInvocationHandler.invoke()
AnnotationInvocationHandler.equalsImpl()
Method.invoke()
...
TemplatesImpl.getOutputProperties()
TemplatesImpl.newTransformer()
TemplatesImpl.getTransletInstance()
TemplatesImpl.defineTransletClasses()
ClassLoader.defineClass()
Class.newInstance()
...
MaliciousClass.<clinit>()
...
Runtime.exec()
JDK7U21原生反序列化利用链分析
JDK7u21的核心点就是sun.reflect.annotation.AnnotationInvocationHandler,我们来看看AnnotationInvocationHandler这个方法
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_动态代理](https://file.cfanz.cn/uploads/png/2022/10/31/2/7DOdD76964.png)
再看
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_动态代理_02](https://file.cfanz.cn/uploads/png/2022/10/31/2/c7R620FI68.png)
可以很清楚的分析到equalsImpl这个方法
首先是利用反射获取this.type中的所有方法,之后进行遍历其中的方法并执行,如果我们把this.type赋为一个类,岂不是能调用里面的所有方法了,还记得那个TemplatesImpl对象么,我们就可以利用它来进行字节码的加载执行了
接下来我们发现在AnnotationInvocationHandler下面的invoke方法
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_字节码_03](https://file.cfanz.cn/uploads/png/2022/10/31/2/c84c3CG69K.png)
这里我们其实发现,它实现了InvocationHandler
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_反序列化_04](https://file.cfanz.cn/uploads/png/2022/10/31/2/d8ScdDYc22.png)
因此我们不难想到一个东西,动态代理,当调用equal方法时,就能实现完整的利用链,这里前辈们想到的是利用HashSet,因为HashSet中储存的对象不允许重复,所以在添加对象的时候,势必会涉及到比较操作。
可以看到在HashSet的readObject方法
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_字节码_05](https://file.cfanz.cn/uploads/png/2022/10/31/2/0210DMcK2e.png)
这里调用了equal方法,但是从函数当中也能看出前提是他们的hash值相等
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_反序列化_06](https://file.cfanz.cn/uploads/png/2022/10/31/2/2d0eddQEfH.png)
接下来我们就要让proxy对象的哈希值,等于TemplateImpl对象的哈希值,我们来看看hash的计算方法
我们来看看这里面的hash方法
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_动态代理_07](https://file.cfanz.cn/uploads/png/2022/10/31/2/Ma10Y28567.png)
这里我们发现主要是对象的hashCode方法
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_动态代理_08](https://file.cfanz.cn/uploads/png/2022/10/31/2/266Tbb0651.png)
那我们就来看看这两个方法,首先是TemplatesImpl的hashcode方法,无法Debug调试跟踪,最后网上说是一个Native方法,难怪,但是我们不难发现每一次运行都在变,如何处理看后面分析
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_反序列化_09](https://file.cfanz.cn/uploads/png/2022/10/31/2/d20QB6KT16.png)
而看看我们代理的HashCode呢,会通过AnnotationInvocationHandler的invoke ,进而调用到AnnotationInvocationHandler的hashCodeImpl
我们看看hashCodeImpl,它遍历memberValues中的每个key和value,计算 (127 * key.hashCode()) ^ value.hashCode()并求和
private int hashCodeImpl() {
int var1 = 0;
Entry var3;
for(Iterator var2 = this.memberValues.entrySet().iterator(); var2.hasNext(); var1 += 127 * ((String)var3.getKey()).hashCode() ^ memberValueHashCode(var3.getValue())) {
var3 = (Entry)var2.next();
}
return var1;
}再来看这个当只有一个key和value时,简化成 了(127 * key.hashCode()) ^ value.hashCode()
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_字节码_10](https://file.cfanz.cn/uploads/png/2022/10/31/2/d14R9QT090.png)
因此不难想到当key.hashCode()等于0时,任何数异或0的结果仍是他本身,所以该哈希简化成value.hashCode() 当 value 就是TemplateImpl对象时,这两个哈希就变成完全相等,因此我们只需要拿到一个hashCode是0的对象,网上给跑出来的是字符串f5a5a608
我们整理下利用思路
- 构造TemplatesImpl并将执行的字节码赋值
- 实例化一个HashMap,并添加key
f5a5a608,恶意构造好的TemplatesImpl加入到map中 - 利用反射实例化
AnnotationInvocationHandler类 - 为
AnnotationInvocationHandler对象设置动态代理 - 实例化
HashSet,并将TemplatesImpl和设置的代理这两个对象放进去
流程跟踪
首先通过readObject调用,之后
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_反序列化_11](https://file.cfanz.cn/uploads/png/2022/10/31/2/4960NRSSf0.png)
跟进去看看,首先第一个对象Hash计算完添加
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_反序列化_12](https://file.cfanz.cn/uploads/png/2022/10/31/2/RPQ193b08S.png)
由于第二个对象hash与第一个相同,调用equal方法
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_动态代理_13](https://file.cfanz.cn/uploads/png/2022/10/31/2/866J8P8781.png)
通过动态代理触发equalsImpl的调用
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_字节码_14](https://file.cfanz.cn/uploads/png/2022/10/31/2/0896Y2cXL7.png)
接下来就是遍历Template里面的方法并通过反射执行,可以看到这里有执行newTransformer
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_动态代理_15](https://file.cfanz.cn/uploads/png/2022/10/31/2/07QP8ZX80Q.png)
调用getTransletInstance方法
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_字节码_16](https://file.cfanz.cn/uploads/png/2022/10/31/2/N3d3727N56.png)
继续跟踪调用defineTransletClasses方法
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_字节码_17](https://file.cfanz.cn/uploads/png/2022/10/31/2/fac06K6769.png)
跟入defineClass
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_反序列化_18](https://file.cfanz.cn/uploads/png/2022/10/31/2/R4V8Q4VcS5.png)
加载字节码
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_反序列化_19](https://file.cfanz.cn/uploads/png/2022/10/31/2/NQ961L4ebO.png)
别忘了这里有一个验证加载的字节码的对象必须是class com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet的子类哦
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_字节码_20](https://file.cfanz.cn/uploads/png/2022/10/31/2/26Q0891981.png)
实例化
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_反序列化_21](https://file.cfanz.cn/uploads/png/2022/10/31/2/0c22P446eB.png)
成功弹出计算器
![在这里插入图片描述 [Java反序列化]JDK7U21原生反序列化利用链分析_动态代理_22](https://file.cfanz.cn/uploads/png/2022/10/31/2/31L70H571F.png)
参考文章
动态代理JavaThings/JDK7u21【技术分享】JDK7u21反序列化jdk7u21反序列化调试
