URLDNS
0x00 sink
这个比较简单,网上类似文章很多,简要介绍一下。 java.net.URLStreamHandler.getHostAddress() 方法会触发一次查询,而该方法可以通过 java.net.URL 类的 equals() 和 hashcode() 方法调用。

0x01 source
soure 点选用 HashMap,具体原理可以参考 hashMap原理 这篇文章。总结出当前分析需要关注的点 put() 函数会调用 hashCode() 计算 key 的 hash,然后再计算index。
而在 HashMap 的 readObject() 中调用 putVal() 计算 key 的 hash,所以用来触发。

在序列化时会调用 put() 方法,这时候会触发 hashCode() 方法,hashCode 属性值会被设为 -1,经过 java.net.URL.hashCode() 中判断,不会触发后续流程,所以需要反射修改 hashCode 值。
ysoserial 中实现了自定义的 URLStreamHandler 使得生成 gadget 时调用自定义 getHostAddress() 方法,避免提前触发dns查询。

0x02 类探测
在调用 HashMap 的 putVal() 前调用了这两个方法,而在 readObject() 中,当类不存在时会抛出 ClassNotFoundException 异常,也就不会触发到后续的请求,因此可以将 value 值插入为 Class 对象实现类探测。
K key = (K) s.readObject();
V value = (V) s.readObject();

本地已有的类可以通过 Class.forName(className); 获取,如果想探测任意类呢?可以使用 javassist
ClassPool.getDefault().makeClass(className).toClass();