JAVA反序列化之反射+URLDNS链条
JAVA反序列化之反射+URLDNS链条
前言
首先,我们已经认识了什么是反射,简单的说就是动态的获取并构造出一个类对象,并可以执行类其中的方法
其实呢,这个URLDNS也是一个反序列化的链条,既然如此,那就符合我们构造反序列化链条的一般方法
URLDNS链条构造
入口
既然是反序列化,那第一步,就得看看,哪里作为入口类比较的合适了,入口类的条件:
第一:接受广泛的参数类型(人话就是最好接受其它类作为参数)
第二:可以反序列化
第三:必须重写readObject类
既然如此,那么我们第一个考虑的就是Map类中的HashMap类,我们去看看其中的readObjecth函数,做进一步的分析
我们观察一下这个readObject方法的最后一个循环函数,发现他会对我们传入的K和V进行反序列化,然后最重要的是,它调用了hash(key)这个方法,那这个方法是干啥的呢,我们在HashMap类中继续寻找一下
我们发现了这个静态方法,如果key不等于null,就会执行key中的hashCode方法,首先这个if条件,几乎等于没有条件,我们肯定是会传东西进去的,再者这个hashCode方法其实很玄妙的,不是这个函数有多厉害,而是这个函数很多类都有并且重写过,所以理论上,我们传入的类不同,就会执行不同类中的hashCode方法,这样就能创造无限的可能
执行类
那我们归根结底是找一个能够执行DNS解析的类,即使找到一个看起来靠谱的入口类,如果和DNS解析的类扯不上关系,也白搭,那JAVA中哪个类是支持DNS解析的呢
当然是我们的URL类,首先URL类继承了反序列化的接口,是可以实现反序列化的,满足了这个条件之后,我们发现,URL类也重写了hashCode方法,这就很好了,这意味着我们hashMap中传入的K只要是一个URL类对象,那么在反序列化时就会调用URL类中的hashCode方法,我们去看看这个函数如何执行的
但是此时我们看不到一点点执行DNS解析的迹象,只能看到这个hashCode方法里面,又调用了一个handler.hashCode(this),这个this不必多少,谁调用这个函数,谁就是this,在这里这个this就是URL类对象,那这个handler又是啥东西呢?
是一个其它的类,我们跟进去查看其中的hashCode方法
我们发现了这个类中的hashCode方法会调用getHostAddress函数,这个函数干啥的呢,其实就是解析域名的,到这里我们发现这条链是可行的,有的人可能会说这是保护方法,但是由于URL类中声明了handler这个成员变量,所以这里是可以做到访问其中的保护方法的,所以我们只能传入一个URL类对象,并将他作为key传入HashMap,这个问题就解决了,我们先按照分析构造payload
Payload初构造
1 | public class Main { |
但是,当我们如此构造好payload,准备对hashMap进行序列化时,我们发现此时,DNS已经解析了
这是为啥啊,问题肯定不是出在URL的构造函数上了,那就只能在map.put上,我们去看看map.put都干了什么
put函数调用了hash(key)函数,和该类反序列化里面一样的函数,怪不得会直接触发DNS的解析,这样会影响我们对漏洞是否执行的判断,更要命的是
这个URL类中的hashCode函数一旦执行,就会返回一个hashCode成员变量,这个变量在第一次调用的时候肯定是-1没错,但是当我们使用完map.put之后,这个值就就绝对不是-1了,那就坏大事了,当我们反序列化时,由于hashCode不是-1,所以链子就断了,执行不下去了
那我们如何才能构造好链子呢,只有一个办法,那就是利用反射,我们在使用hash.put函数前,将URL中的hashCode成员变量改成非-1的其它值,然后使用map.put函数传入URL类,然后在我们序列化map之前,再次利用反射将其改回-1
payload如下:
1 | class SerializeUtil { |
执行结果
结语
DNS这条链子没有什么异常的难点,适合在学了原生的反序列化后学习的一条链子,从中能更好的理解JAVA的反序列化和反射机制,加油,师傅们,共勉