- 类别:javanative 别名:— 优先级:9
- 作者:—
- 依赖:
com.fasterxml.jackson.core:jackson-databind>2.9
把内层对象包进 com.fasterxml.jackson.databind.node.POJONode,使其在 toString() 被调用时(POJONode.toString() → 序列化该 POJO → 逐个调用其所有字段的 getter)触发下游 getter 型 sink。是一个「以 toString 为入口、以 getter 为出口」的桥接 gadget,常用于 Hessian、二次反序列化等需要 toString 触发点的场景。
- 入口
tags:ToString—— 本 gadget 需要由一个「会调用其内层对象toString()」的上一环来激活(如BadAttributeValueExpException、Hessian 的toString触发点、XString等)。 - 衔接
nextTags:TemplatesImplWrapperChain、TemplatesImplChain、LdapAttributeChain、SignedObjectChain、MapMessageChain、DataSourceChains、DataSourceWrapperChain—— 之后可接任意「暴露危险 getter」的 gadget,其中最常见的是 TemplatesImpl(getOutputProperties→newTransformer→ 字节码 defineClass)。 excludes:无。
public Object getObject(Object object) throws Exception {
POJONode node = new POJONode(object); // 把内层对象包成 POJONode
this.pre(); // 关键:清除 writeReplace 干扰
return node;
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
return this.getObject(chain.doCreate(context)); // 先取内层对象再包裹
}invoke 遵循「由内向外」构建约定:chain.doCreate(context) 先产出内层的 getter 载体(如 TemplatesImpl),再用 POJONode 把它包起来。反序列化后一旦有人对该 POJONode 调用 toString(),Jackson 会对内部 POJO 做序列化式遍历,逐个反射调用其 getter,从而触达 sink。
public void pre() {
ClassPool pool = ClassPool.getDefault();
try {
String classname = "com.fasterxml.jackson.databind.node.BaseJsonNode";
ClassLoader loader = Thread.currentThread().getContextClassLoader();
CtClass ctClass = pool.get(classname);
CtMethod writeReplace = ctClass.getDeclaredMethod("writeReplace");
ctClass.removeMethod(writeReplace); // 删除 writeReplace
ctClass.toClass(loader);
ctClass.toClass(Class.forName(classname).getClassLoader());
} catch (Exception exception) {
// empty catch block
}
}pre() 借助 Javassist 在运行时把 BaseJsonNode(POJONode 的父类)里的 writeReplace 方法删除。jackson-databind 高版本给 BaseJsonNode 加了 writeReplace,序列化 POJONode 时会被替换成一个无害的中间对象,导致 payload 失效;这里通过热修改字节码去掉该方法,保证 POJONode 本体能被原样序列化。注意这是对生成端 JVM 的自身类的修改,用于让 java-chains 能顺利产出可用的 POJONode 字节流。
本类无独立 @Param。要触发哪个 getter 由下游 gadget 通过链上下文决定(如 TemplatesImpl 注入 outputProperties)。
- 适用
jackson-databind > 2.9(存在POJONode且BaseJsonNode带writeReplace的版本)。 - 原理链路:
toString()→POJONode.toString()→ 遍历序列化 POJO → 反射调用该对象所有字段的 getter。 - 不稳定性(源码 description 明确指出):getter 的调用顺序不固定,有时
outputProperties会先于stylesheetDOM被取值,只有这种顺序下 TemplatesImpl 才能成功触发。因此该链存在概率性失败,实战中可能需要多次尝试。
- Hessian Jackson 链(
[JacksonToString, SignedObject, JavaNativeSerialization, Jackson, TWrap, TemplatesImpl, BytecodeConvert, Exec]) - JDK17 RCE链(
[EventListenerListToStringHighJDK, JacksonToString, TWrapHighVersion, TemplatesImpl2, BytecodeConvert, Exec]) - JDK17 RCE链2(
[TextAndMnemonicHashMapToStringHighJDK, JacksonToString, TWrapHighVersion, TemplatesImpl2, BytecodeConvert, Exec])
- 上游(提供
ToString触发点):EventListenerListToStringHighJDK、TextAndMnemonicHashMapToStringHighJDK、BadAttributeValueExpExceptionToString。 - 下游(
nextTags指向的 getter 载体):TemplatesImpl、TWrap/TWrapHighVersion(TemplatesImpl 包装器)、LdapAttribute、JdbcRowSetImpl。 - 同族:
FastjsonToString1/FastjsonToString2(同为 toString→getter 桥接,走 fastjson 的JSONObject.toString)。