JAVA安全-URLDNS链
本文最后更新于:2022年11月23日 晚上
JAVA安全-URLDNS链
1:前言
URLDNS链是java反序列化链中最简单的一条链子,也是java原生态的一条利用链,通常用于存在反序列化漏洞进行验证的,不存在版本限制,首先我们来了解一下java反序列化:Java提供了一种对象序列化的机制,用一个字节序列表示一个对象,该字节包含对象的数据、对象的类型、对象的存储属性。字节序列写出到文件的过程叫做序列化。序列化对象会通过ObjectOutputStream
的writeObject
方法将一个对象写入到文件中。
而反序列化是使用了readObject
方法进行读取并还原成在序列化前的一个类。如果反序列化的数据是可控的情况下,那么我们就可以从某个输入点输入恶意代码,再去查找在哪个点,我们的输入会被一层一层的带去到我们的触发点去,而这一步叫做寻找利用链的步骤。
2:测试
查看hashmap的接口中的readObject方法
再往下看到hash方法,跟进之后发现判断语句 hash中传入一个对象如果不为空则调用hashcode方法
跟进之后发现判断,hashcode值不为-1则停止,为-1则继续,hashcode默认值为-1,所以会继续调用handler.hashcode方法
后续跟进得出URLDNS整条链的调用流程为:
HashMap->readObject()
HashMap->hash()
URL->hashCode()
URLStreamHandler->hashCode()
URLStreamHandler->getHostAddress()
InetAddress->getByName()
InetAddress.getByName方法会使用远程请求,进行获取主机的ip,那么这时候就会触发一次请求,到了这里我们的dnslog平台,就可以收到响应了。这就是这个URLDNS链的一个触发点。
现在进行测试:
-
断点调试,调用hashmap.put方法前,是不会触发解析的,调用后能触发解析,dnslog也收到了解析信息,因为缓存多次重复运行,dnslog也不会再有新的记录
以上是正常的hashmap做一个dns解析的访问
通过反射来修改hashcode的默认值从而导致前面说的hashcode方法停止继续调用而不能访问getHostAddress方法,最终解析失败。所以在进行反序列化时还要讲hashcode值改回-1
所以在序列化之前要将hashcode值改回-1,然后运行之后再反序列化最后成功解析。
3:总结
java.util.HashMap重写了readObject方法,在反序列化时会调用 hash 函数计算 key 的 hashCode,在计算hashCode()的时候,就会调用URLStreamHandler.hashCode()触发getHost方法对目标进行DNS解析,其主要目的用来检测是否存在反序列化漏洞