Java安全—原生反序列化重写方法链条分析触发类
前言
在Java安全中反序列化是一个非常重要点,有原生态的反序列化,还有一些特定漏洞情况下的。今天主要讲一下原生态的反序列化,这部分内容对于没Java基础的来说可能有点难,包括我。
序列化与反序列化
序列化:将内存中的对象压缩成字节流
反序列化:将字节流转化成内存中的对象
简单来说就是把对象转换为字节流,方便存储在文件、数据库等。
Java里面常见的序列化与反序列化协议。
JAVA内置的writeObject()/readObject()
JAVA内置的XMLDecoder()/XMLEncoder
XStream
SnakeYaml
FastJson
Jackson
假如我要传输这一串代码,直接复制的话肯定不行,因为里面有大量的空格和换行,直接复制会出错的。所以就要用到序列化,把它加密成一串字节流进行传输,然后再反序列化解密还原成代码即可。
原生反序列化
Java新建一个项目,叫serialization。
随便选个版本即可。
创建一个user类,并写入代码。
再创建一个类叫serialization_demo,用来实现序列化操作的。简单来说代码就是把我们的user类里面的对象进行序列化操作,并且把结果写入ser.txt里面。
package com.sf.maven.serialization;public class serialization_demo {public static void main(String[] args) throws IOException {// 创建一个用户对象,引用UserDemouser u = new user("wlw", "gay", 30);// 调用方法进行序列化SerializableTest(u);// ser.txt 就是对象u序列化的字节流数据}public static void SerializableTest(Object obj) throws IOException {// 使用 ObjectOutputStream 将对象 obj 序列化后输出到文件 ser.txtObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.txt"));//序列化操作oos.writeObject(obj);// 关闭流oos.close();}
}
直接运行可以看到输入了我们的对象。
在旁边的目录下可以看到一个ser.txt文件,打开发现里面是字节流,这个ser.txt就是user对象序列化的结果。
我们再来试试反序列化,看看能不能把字节流还原。先创建一个类叫Unserialization_demo,写入以下代码,就是从ser.txt读取字节流,再反序列还原输出。
package com.sf.maven.serialization;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;public class Unserialization_demo {public static void main(String[] args) throws IOException, ClassNotFoundException {// 调用下面的方法,传输 ser.txt,解析还原反序列化Object obj = UnserializableTest("ser.txt");// 对 obj 对象进行输出,默认调用原始对象的 toString 方法System.out.println(obj);}// 反序列化方法public static Object UnserializableTest(String Filename) throws IOException, ClassNotFoundException {// 读取 Filename 文件进行反序列化还原ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object o = ois.readObject();// 返回反序列化后的对象return o;}}
直接运行好吧,可以看到输出了对象数据。
这就是原生的序列化和反序列化操作,就是把数据转换成字节流然后再封装成一个文件,然后再还原。
重写方法
OK,那么现在我们来讲一下怎么利用这个玩意,我们可以看到readObject()这个方法是来自ObjectinputStream.java这个文件。
而这个Java文件是来自src.zip里面,是我们JDK自带的东西。
现在我们来重写这个readObject这个方法,什么意思呢,就是当我们进行反序列化的时候不是会调用JDK自带的readObject()吗,那现在我们自己写一个readObject方法,让它在进行反序列的时候去调用我们自己写的readObject,而不是调用JDK自带的readObject。
在我们的user类里面加入重写readObject的代码,就是命令执行计算机。
重新对user进行序列化,生成新的ser.txt文件。
再对ser.txt进行反序列化,成功弹出了计算机!!!说明我们重写的方法有用,在反序列化的时候它执行的是user里面我们自己写的readObject,而不是JDK自带的。
我们来步入跟进一下代码,为了直观我们在readObject添加一行代码。
设置一个断点进行调试。
点击步入可以看到此时的Filename等于我们的ser.txt。
继续步入,执行到我们的ObjectInputStream读取文件这里。
接着步入跳到了ObjectInputStream.java类这里。
此时我们步出回到了这里。
接着步入,让它调用readObject。
关键的来了,此时我们再步入的话,跳转到了我们的user.java里面的readObject,而不是ObjectinputStream里面的readObject。
toString
上面我们说的方法是属于入口类的readObject危险方法直接调用(我也没搞懂为啥叫这个名字),还有方法就是—构造函数/静态代码块等类加载时隐式执行,说实话好绕口啊。其实我感觉两个都差不多,我们先在user里面重写一下toString。
把我们上面重写的readObject注释掉,重新序列化生成一个ser.txt。
再执行反序列化代码,对ser.txt还原,此时也弹出了计算机。
这是为啥,原来当我们用System.out.println()进行输出的时候,会默认调用toString方法,而toString我们上面添加了启动计算机的命令代码。
HashMap
还有就是如果我们使用的类里面自带readObject方法会不会触发呢,HashMap这个类里面就自带readObject,我们用它试一下。先创建一个类叫HashMap_demo,写入以下代码,就是对hash这个对象进行序列化并输出到url.txt,然后再反序列化。
package com.sf.maven.serialization;
import java.io.*;
import java.net.URL;
import java.util.HashMap;public class HashMap_demo implements Serializable {public static void main(String[] args) throws IOException, ClassNotFoundException{HashMap<URL, Integer> hash = new HashMap<>();URL u = new URL("dnslog地址");hash.put(u, 1);//序列化SerializableTest(hash);//反序列化//UnserializableTest("url.txt");}public static void SerializableTest(Object obj) throws IOException {// 使用 ObjectOutputStream 将对象 obj 序列化后输出到文件 url.txtObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("url.txt"));//序列化操作oos.writeObject(obj);oos.close();}public static Object UnserializableTest(String Filename) throws IOException, ClassNotFoundException {// 读取 Filename 文件进行反序列化还原ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object o = ois.readObject();return o;}
}
直接运行代码先序列化生成一个url.txt。
接着对url.txt进行反序列,可以看到dnslog有回显,说明代码对dnslog进行了解析。
这是咋回事呢,直接来看一下这个利用链。我们引用了HashMap —> readObject本来在ObjectInputStream里面 —> 但是HashMap里面也有readObject —> 所以在反序列化的时候调用的是HashMap的readObject,而不是ObjectInputStream的readObject—>触发HashMap.putVal() —> 触发HashMap.hash() —> 最终触发URL.hashCode()去访问我们dnslog地址。
如果把dnslog地址换成命令,不就是RCE漏洞了吗,这种就是入口参数包含可控类,改类有危险方法,readObject时调用。
总结
虽然今天的内容看起来有点复杂,但总结起来就一件事,想办法调用其它的readObject,而不是去调用原本的readObject。
最后还是要声明一下,以上仅为个人的拙见,如何有不对的地方,欢迎各位师傅指正与补充,有兴趣的师傅可以一起交流学习。
相关文章:

Java安全—原生反序列化重写方法链条分析触发类
前言 在Java安全中反序列化是一个非常重要点,有原生态的反序列化,还有一些特定漏洞情况下的。今天主要讲一下原生态的反序列化,这部分内容对于没Java基础的来说可能有点难,包括我。 序列化与反序列化 序列化:将内存…...
2023考研王道计算机408数据结构+操作系统+计算机组成原理+计算机网络
from: https://blog.csdn.net/weixin_46118419/article/details/125611299 写得很好! 轻重缓急 2023考研计算机408【王-道计算机408】数据结构操作系统计算机组成原理计算机网络 网盘-链接:https://pan.baidu.com/s/13JraxUYwNVPeupdzprx5hA?pwd5h3d 提…...
YOLOv8-ultralytics-8.2.103部分代码阅读笔记-files.py
files.py ultralytics\utils\files.py 目录 files.py 1.所需的库和模块 2.class WorkingDirectory(contextlib.ContextDecorator): 3.def spaces_in_path(path): 4.def increment_path(path, exist_okFalse, sep"", mkdirFalse): 5.def file_age(path__fi…...

「Mac畅玩鸿蒙与硬件34」UI互动应用篇11 - 颜色选择器
本篇将带你实现一个颜色选择器应用。用户可以从预设颜色中选择,或者通过输入颜色代码自定义颜色来动态更改界面背景。该应用展示了如何结合用户输入、状态管理和界面动态更新的功能。 关键词 UI互动应用颜色选择器状态管理用户输入界面动态更新 一、功能说明 颜色…...

ELK(Elasticsearch + logstash + kibana + Filebeat + Kafka + Zookeeper)日志分析系统
文章目录 前言架构软件包下载 一、准备工作1. Linux 网络设置2. 配置hosts文件3. 配置免密登录4. 设置 NTP 时钟同步5. 关闭防火墙6. 关闭交换分区7. 调整内存映射区域数限制8. 调整文件、进程、内存资源限制 二、JDK 安装1. 解压软件2. 配置环境变量3. 验证软件 三、安装 Elas…...

07.ES11 08.ES12
7.1、Promise.allSettled 调用 allsettled 方法,返回的结果始终是成功的,返回的是promise结果值 <script>//声明两个promise对象const p1 new Promise((resolve, reject) > {setTimeout(() > {resolve("商品数据 - 1");}, 1000)…...

linux一键部署apache脚本
分享一下自己制作的一键部署apache脚本: 脚本已和当前文章绑定,请移步下载(免费!免费!免费!) (单纯的分享!) 步骤: 将文件/内容上传到终端中 …...
2022 年 6 月青少年软编等考 C 语言三级真题解析
目录 T1. 制作蛋糕思路分析T2. 找和最接近但不超过K的两个元素思路分析T3. 数根思路分析T4. 迷信的病人思路分析T5. 算 24思路分析T1. 制作蛋糕 小 A 擅长制作香蕉蛋糕和巧克力蛋糕。制作一个香蕉蛋糕需要 2 2 2 个单位的香蕉, 250 250 250 个单位的面粉, 75 75 75 个单位的…...

MySQL - Why Do We Need a Thread Pool? - mysql8.0
MySQL - Why Do We Need a Thread Pool? - mysql8.0 本文主要由于上次写的感觉又长又臭, 感觉学习方法有问题, 我们这次直接找来了 thread pool 的原文,一起来看看官方的开发者给出的blog – 感觉是个大神 但是好像不是最官方的 ,…...
Linux互斥量读写锁
一、互斥量 1.临界资源 同一时刻只允许一个进程/线程访问的共享资源(比如文件、外设打印机) 2.临界区 访问临界资源的代码 3.互斥机制 mutex互斥锁,用来避免临界资源的访问冲突,访问临界资源前申请互斥锁,访问完释放…...
网络安全之IP伪造
眼下非常多站点的涉及存在一些安全漏洞,黑客easy使用ip伪造、session劫持、xss攻击、session注入等手段危害站点安全。在纪录片《互联网之子》(建议搞IT的都要看下)中。亚伦斯沃茨(真实人物,神一般的存在)涉…...

ARM CCA机密计算安全模型之硬件强制安全
安全之安全(security)博客目录导读 [要求 R0004] Arm 强烈建议所有 CCA 实现都使用硬件强制的安全(CCA HES)。本文件其余部分假设系统启用了 CCA HES。 CCA HES 是一个可信子系统的租户——一个 CCA HES 主机(Host),见下图所示。它将以下监控安全域服务从应用处理元件(P…...

【论文笔记】A Token-level Contrastive Framework for Sign Language Translation
🍎个人主页:小嗷犬的个人主页 🍊个人网站:小嗷犬的技术小站 🥭个人信条:为天地立心,为生民立命,为往圣继绝学,为万世开太平。 基本信息 标题: A Token-level Contrastiv…...

C#窗体简单登录
创建一个Windows登录程序,创建两个窗体,一个用来登录,一个为欢迎窗体,要求输入用户名和密码(以个人的姓名和学号分别作为用户名和密码),点击【登录】按钮登录,登录成功后显示欢迎窗体…...

基于ZYNQ-7000系列的FPGA学习笔记3——开发环境搭建点亮一个LED
基于ZYNQ-7000系列的FPGA学习笔记3——开发环境搭建&点亮一个LED 1. 搭建开发环境2. FPGA的开发流程3. 点亮一个LED3.1 实验要求3.2 新建工程3.3 原理图3.4 绘制系统框图3.5 绘制波形图3.6 编写RTL代码3.7 软件仿真3.8 Vivado软件创建工程3.9 分析与综合3.10 设计实现 在上…...
队列-链式描述(C++)
定义 使用链表描述队列时,通常包含以下几个基本要素: 队头指针(Front Pointer):指向队列中第一个(即最早进入队列的)元素的节点。队尾指针(Rear Pointer):指…...

Kali Linux使用Netdiscover工具的详细教程
Kali Linux使用Netdiscover工具的详细教程 引言 在网络安全和渗透测试的过程中,网络发现是一个至关重要的步骤。Netdiscover是Kali Linux中一个非常实用的网络发现工具,它可以帮助用户快速识别局域网中的活动设备。本文将详细介绍如何使用Netdiscover工…...

arkTS:使用ArkUI实现用户信息的持久化管理与自动填充(PersistentStorage)
arkUI:使用ArkUI实现用户信息的持久化管理与自动填充(PersistentStorage) 1 主要内容说明2 例子2.1 登录页2.1.1登陆页的相关说明2.1.1.1 持久化存储的初始化2.1.1.2 输入框2.1.1.3 记住密码选项2.1.1.4 登录按钮的逻辑2.1.1.5 注册跳转 2.1.…...

IntelliJ+SpringBoot项目实战(二十)--基于SpringSecurity实现Oauth2服务端和客户端
在前面的帖子中介绍了SpringSecurityJWT实现了认证和授权的功能。因为基于Oauth2的统一认证在项目需求中越来越多,所以有必要将OAuth2的解决方案也整合进来,这样我们的产品既可以作为一个业务系统,也可以作为一个独立的统一认证服务器。下面详…...

如何实现剪裁功能
文章目录 1 概念介绍2 使用方法2.1 ClipOval2.2 ClipRRect3 示例代码我们在上一章回中介绍了AspectRatio Widget相关的内容,本章回中将介绍剪裁类组件(Clip).闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的剪裁类组件主要是指对子组件进行剪裁操作,常用的…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态
前言 在人工智能技术飞速发展的今天,深度学习与大模型技术已成为推动行业变革的核心驱动力,而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心,系统性地呈现了两部深度技术著作的精华:…...

解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...
如何通过git命令查看项目连接的仓库地址?
要通过 Git 命令查看项目连接的仓库地址,您可以使用以下几种方法: 1. 查看所有远程仓库地址 使用 git remote -v 命令,它会显示项目中配置的所有远程仓库及其对应的 URL: git remote -v输出示例: origin https://…...