总体思路:利用lazy调用decorate()方法的第二个参数Transformer可控,该接口有三个重要的实现类
Transformer可以理解为一个转换器,当做工厂的一个加工程序,进入转换器需要做点事情才能输出,不同的转换器进行不同的处理,如下列举三个 CC1链子用到的转换器
- ConstantTransformer:当调用其 transform 方法时,它将返回构造时传入的 对象
- InvokerTransformer:初始化此类后,调用 transform 方法将通过反射创建对象实例
- ChainedTransformer:将各个 Transformer 连接在一起,使用上一个 Transformer 的结果作为下一个 Transformer 的输入
使用方法3链式调用方法1生成一个Runtime对象,同时利用方法2去获取Runtime对象的getRuntime()运行时环境,再获取invoke来执行相关命令(包括系统敏感的命令),这里涉及到Java反射机制的原理
要想触发decorate()方法,需要调用map.get(),但是yso不需要lazymap直接使用该方法,于是可以使用AnnotationInvocationHandler的invoke方法(实现了调用map.get()方法)
AnnotationInvocationHandler类是动态代理InvocationHandler接口的一个实现类,使用AnnotationInvocationHandler来创建一个上边map的动态代理proxy_map
由于需要执行AnnotationInvocationHandler的invoke方法,所以需要再对proxy_map进行AnnotationInvocationHandler代理来执行自身的invoke方法
Gadget chain:
ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()
CommonsCollections
Java版本为 1.7
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
LazyMap
简介:修饰另一个 map,当调用 map 中不存在的 key 时使用工厂创建对象
多说无益,上代码
package com.chuxia.cc1;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.Map;
public class TestLazyMap {
public static void main(String[] args) {
// 定义处理不存在 key 的情况,可以是 Transformer 也可以是 ChainedTransformer 链子
// 用于反转调用不存在的 key 值
final Transformer reverseString = new Transformer() {
public Object transform(Object object) {
String name = (String) object;
String reverse = StringUtils.reverse(name);
return reverse;
}
};
Map names = new HashMap();
// 将处理链传给 lazyMap
Map lazyMap = LazyMap.decorate(names, reverseString);
// lazyMap 为空,测试调用不存在 key
String name = (String) lazyMap.get("chuxia");
System.out.println("name:" + name);
// put 一个键值
lazyMap.put("chuxia", "TestLazyMap");
// key 存在,不进入处理链
name = (String) lazyMap.get("chuxia");
System.out.println("name:" + name);
}
}
可以看到 La