Skip to content

Latest commit

 

History

History
58 lines (48 loc) · 4.36 KB

File metadata and controls

58 lines (48 loc) · 4.36 KB

调用Equals方法(HotSTSourceEquals)

  • 类别:common 别名:— 优先级:—(@Deprecated
  • 作者:—
  • 依赖spring-aoporg.springframework.aop.target.HotSwappableTargetSource

作用

利用 HashMap.readObject 反序列化时对哈希碰撞键触发 key.equals() 的特性,把两个攻击者可控对象包进 HotSwappableTargetSource,在反序列化瞬间强制发起一次 obj1.equals(obj2) 调用。是一个「把 Java 原生/Hessian 反序列化入口转换为任意 equals 调用」的跳板构件,为下游 Equals 型 gadget(如 XString、AbstractTableModel 等借 equals 触发 toString/getter 的载体)提供入口。

链接标签

  • 入口 tagsJavaNativeDeserializeHessianDeserialize —— 承接 Java 原生反序列化与 Hessian 反序列化两类入口。
  • 衔接 nextTagsEquals —— 之后需接一个「利用 equals 触发危险行为」的 gadget,由它向本 gadget 提供参与比较的两个对象。
  • excludes:无。

源码剖析

@GadgetTags(tags={"JavaNativeDeserialize", "HessianDeserialize"}, nextTags={"Equals"})
@Deprecated
public class HotSTSourceEquals implements Gadget {
    public Object getObject(Object obj1, Object obj2) throws Exception {
        HotSwappableTargetSource h1 = new HotSwappableTargetSource(obj2);
        HotSwappableTargetSource h2 = new HotSwappableTargetSource(obj1);
        return PayloadHelper.makeMap(h1, h2);
    }

    @Override
    public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
        Object[] objects = (Object[]) chain.doCreate(context);
        Object getterObject = context.get(ContextTag.FASTJSON_HANDLE_BYPASS_KEY);
        Object resultObject = this.getObject(objects[0], objects[1]);
        if (getterObject != null) {
            return CommonMethod.listWrap(getterObject, resultObject);
        }
        return resultObject;
    }
}
  • invokechain.doCreate(context)约定内层 gadget 返回一个长度为 2 的 Object[]objects[0]objects[1]),即下游 Equals gadget 需要参与 equals 比较的一对对象。
  • getObject 把这两个对象分别包进两个 HotSwappableTargetSourceh1 持有 obj2h2 持有 obj1HotSwappableTargetSource.equals 的语义是「对方也是 HotSwappableTargetSource 时,比较各自持有的 target」,即 h1.equals(h2) 最终展开为 obj2.equals(obj1)(对应 description 中「obj1、obj2 对象指定方法:obj1.equals(obj2)」的效果)。
  • PayloadHelper.makeMap(h1, h2) 构造一个 HashMap,把 h1h2 放成哈希碰撞的两个键。HashMap.readObject 重建时会对落入同一桶的键调用 equals,从而在反序列化过程中自动触发上述 equals 调用——这正是经典的 HashMap equals 触发原语。
  • 末尾的 FASTJSON_HANDLE_BYPASS_KEY 分支:当上下文中存在 Fastjson 绕过对象时,用 CommonMethod.listWrap 把结果与绕过对象一起包成 List,用于 Fastjson 场景下的额外封装;普通场景直接返回 HashMap

参数(@Param)

本类无 @Param,无用户可配字段。参与比较的两个对象完全由下游 Equals gadget 通过 chain.doCreate 提供。

适用版本与原理要点

  • 依赖 spring-aop 提供 HotSwappableTargetSource(其 equals 会比较内部 target),故目标须存在 spring-aop。
  • 触发链:HashMap#readObject → 桶内键碰撞 → HotSwappableTargetSource#equalsobj2.equals(obj1)
  • 本类被标注 @Deprecated:官方更倾向使用其它 equals 入口(如直接 HashMapEquals/HashTableEquals 等),此构件保留兼容。使用时须确保内层 gadget 返回 Object[]{obj1, obj2} 结构,否则 invoke 中的强制类型转换会失败。

所属预设链

自由构件,未直接出现在 51 条预设链中(usedInChains 为空)。可与需要 equals 触发的下游 gadget 自由组合。

关联

  • 上游入口:Java 原生 / Hessian 反序列化 Payload。
  • 下游(nextTags=Equals):需要 obj1.equals(obj2) 触发危险行为的 gadget(XString 系、借 equals 派生 toString/getter 的载体)。
  • 同族(equals 触发原语):HashMapEqualsHashTableEqualsConcurrentHashMapEquals