Skip to content

Latest commit

 

History

History
56 lines (46 loc) · 4.9 KB

File metadata and controls

56 lines (46 loc) · 4.9 KB

AudioFileFormat$Type 调用toString(AudioFileFormat)

  • 类别:common 别名:— 优先级:—
  • 作者:—
  • 依赖jdk:javax.sound.sampled.AudioFileFormat$Type(纯 JDK 内置类,无第三方依赖)

作用

利用 JDK 内置类 javax.sound.sampled.AudioFileFormat$Typeequals() 会调用参数对象 toString() 这一特性,把「一次 equals 调用」转换成「一次任意对象的 toString 调用」。是 equals → toString 的桥接构件(trampoline),用于把上游的哈希碰撞/equals 触发点接到下游的 toString 型 sink。

链接标签

  • 入口 tagsEqualsNotForJavaSerializable
    • Equals —— 表示本 gadget 需要一个「会触发 equals() 比较」的上游环(如 HashMapEquals/HashTableEquals/ConcurrentHashMapEquals),由它对本 gadget 产出的两个元素调用 a.equals(b)
    • NotForJavaSerializable —— 标记本产物(Object[] 数组 + AudioFileFormat$Type 未初始化实例)不能走 Java 原生序列化通道(该 Type 实例经 createWithoutConstructor 生成、字段不完整,原生 writeObject 会出错),仅适用于 Hessian/JSON 等按字段序列化的入口。
  • 衔接 nextTagsToString —— 本 gadget 之后必须接一个「暴露危险 toString()」的 gadget(如 JacksonToStringXBeanToStringFastjsonToString1/2)。
  • excludes:无。

源码剖析

@GadgetTags(tags={"Equals", "NotForJavaSerializable"}, nextTags={"ToString"})
public class AudioFileFormat$TypeToString implements Gadget {
    public Object getObject() throws Exception {
        Object type = Reflections.createWithoutConstructor("javax.sound.sampled.AudioFileFormat$Type");
        return type;
    }

    @Override
    public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
        Object obj2 = chain.doCreate(context);          // 内层对象:一个 toString 型 gadget 的产物
        Object obj1 = this.getObject();                 // AudioFileFormat$Type 未初始化实例
        Object[] objects = new Object[]{obj1, obj2};    // 成对返回,供上游 equals 消费
        return objects;
    }
}
  • getObject()Reflections.createWithoutConstructor(...) 通过 Unsafe/反射跳过构造器实例化 AudioFileFormat$Type。关键在于:不走构造器就不会给内部的 name(类型字符串)字段赋值,使其保持为 null
  • AudioFileFormat$Typeequals() 是 JDK 内置逻辑,等价于 toString().equals(that.toString());当自身 toString()(即 name)为 null 时,会走到「比较对方 toString() 是否为 null」的分支,从而对参数对象 obj2 调用 obj2.toString()。这一步正是触发下游 toString sink 的引信。
  • invokechain.doCreate(context) 取得内层 toString gadget 的产物 obj2,再把 obj1(Type 实例)与 obj2 打包成 Object[]{obj1, obj2} 返回。上游的 Equals 型 gadget(如 HashMapEquals)会把数组两元素放进哈希容器制造碰撞,反序列化时触发 obj1.equals(obj2)obj2.toString()

关键点:本 gadget 自身不发起任何比较,只负责「构造一个 equals 会回调 toString 的载体」并与目标对象配对;真正的 equals 触发由上游容器 gadget 完成,真正的 RCE 由下游 toString gadget 完成。

参数(@Param)

本类无 @Param 可配参数;目标 toString 载体由 chain.doCreate 注入的内层对象决定。

适用版本与原理要点

  • 依赖仅为 JDK 内置 javax.sound.sampled.AudioFileFormat$Type,无第三方库要求。
  • 依赖 equals()→toString() 的 JDK 语义,该行为在各主流 JDK 版本稳定存在。
  • 因产物含未初始化实例且以 Object[] 承载,NotForJavaSerializable 标签限定其只能用于非 Java 原生、按字段重建对象的序列化协议(Hessian、Fastjson、Jackson 等)。
  • AudioFormat(Encoding 版)原理完全一致,属同一族的可替换构件,用于绕过针对某一具体类的黑名单。

所属预设链

自由构件,未直接出现在 51 条预设链中(usedInChains 为空)。可在 Hessian/JSON 二次反序列化场景中手动组合:HashMapEquals → AudioFileFormat → JacksonToString → …

关联