【Java安全】ysoserial-URLDNS链分析

前言

Java安全中经常会提到反序列化,一个将Java对象转换为字节序列传输(或保存)并在接收字节序列后反序列化为Java对象的机制,在传输(或保存)的过程中,恶意攻击者能够将传输的字节序列替换为恶意代码进而触发反序列化漏洞。其中最经典的反序列化漏洞利用工具——ysoserial,下面就分析学习一下ysoserial中的URLDNS链,以便更好地理解反序列化漏洞。

ysoserial简单分析

下载ysoserialhttps://github.com/frohoff/ysoserial项目源码,导入IDEA,并在pom.xml中搜索mainclass,寻找程序的入口点
【Java安全】ysoserial-URLDNS链分析_第1张图片在程序运行之前,先设置两个参数(URLDNS “http://xxxx.dnslog.cn”),否则运行IDEA会报错。
【Java安全】ysoserial-URLDNS链分析_第2张图片简单分析一下 GeneratePayload 的main方法,首先会判断是否传入两个参数, 如果不是则打印帮助信息 ,是的话则对两个参数依次赋值为payloadType和command。接着实例化一个payloadClass对象,跟进一下getPayloadClass方法【Java安全】ysoserial-URLDNS链分析_第3张图片
getPayloadClass会返回一个反射的class对象,该class对象为GeneratePayload的class对象的包名+字符串“payloads”+我们传入的第一个参数className(也就是payloadType)
【Java安全】ysoserial-URLDNS链分析_第4张图片对应ysoserial中写好的URLDNS脚本,也就是说,我们传入的第一个参数是找到ysoerial的payload脚本。
【Java安全】ysoserial-URLDNS链分析_第5张图片后续会实例化payloadClass,并调用getObject方法,传入我们传入的第二个参数command。跟进getObject方法中,分析传入command后,程序是如何处理的。

【Java安全】ysoserial-URLDNS链分析_第6张图片

发现最终会跳转到URLDNS中
【Java安全】ysoserial-URLDNS链分析_第7张图片

那么以上操作就是根据传入的参数,定位到利用链的类文件中,调用该类的 getObject方法,生成并返回paylaod。
URLDNS类我们先放到一边,继续分析 GeneratePayload 中的main方法。
【Java安全】ysoserial-URLDNS链分析_第8张图片之后会调用 serialize方法,将URLDNS类中返回的值(生成的payload)序列化并打印输出。
【Java安全】ysoserial-URLDNS链分析_第9张图片

URLDNS链分析

URLDNS为Java的原生类,利用效果只是触发一次DNS请求,并不会命令执行,适用于验证是否存在反序列化漏洞。
在URLDNS.java中,作者已经给出了Gadget chain
【Java安全】ysoserial-URLDNS链分析_第10张图片我们先看第53行代码,首先声明了一个URLStreamHandler类,因为URLStreamHandler是个抽象类,不能够被实例化,因此创建了个URLStreamHandler的子类SilentURLStreamHandler。并实现父类URLStreamHandler的抽象方法openConnection。
【Java安全】ysoserial-URLDNS链分析_第11张图片但为什么要重写getHostAddress方法呢,其实我们运用最简单粗暴的方法,将重写方法注释掉,对比没注释之前,有啥区别:区别在于,重写getHostAddress,在我们使用ysoserial生成payload时,不会触发payload,DNSLOG接收不到请求。即因为方法直接返回为Null,不会请求我们的hostAddress
【Java安全】ysoserial-URLDNS链分析_第12张图片而且在URL.java中,handler被transient关键字修饰,在序列化对象的时候,handler属性不会被序列化。意味着重写的方法并不会带进我们的payload中,这样我们在触发反序列化漏洞时,getHostAddress并没有被重写,能够正常请求我们的网址。这也是我觉得很精妙的一个地方,写ysoserial的人真是个天才!太牛*了!
【Java安全】ysoserial-URLDNS链分析_第13张图片然后查看HashMap类,发现HashMap实现了Serializable序列化接口
【Java安全】ysoserial-URLDNS链分析_第14张图片重写了readObject方法
【Java安全】ysoserial-URLDNS链分析_第15张图片在重写的readObject方法中,有调用putVal方法进行一个hash计算
【Java安全】ysoserial-URLDNS链分析_第16张图片调试,跟进putVal方法, 参数key和value都为输入的dnslog地址

在这里插入图片描述继续跟进,这里注意(标重点),调用的是key.hashCode(),即HashMap的参数u,顺利的从HashMap.hash()跳转到URL.hashCode()。
在这里插入图片描述
这里hashCode()方法会对hashCode属性重新赋值
【Java安全】ysoserial-URLDNS链分析_第17张图片这里调用了 URLStreamHandler 类的hashCode方法,参数(URL)u为传入的DNSLOG地址
【Java安全】ysoserial-URLDNS链分析_第18张图片通过getProtocol方法,获取 协议类型——http
【Java安全】ysoserial-URLDNS链分析_第19张图片接下来这里进行一个if判断,h的值会加上portocal的hashCode()方法的返回值,跟进protocol.hashCode()方法
【Java安全】ysoserial-URLDNS链分析_第20张图片继续往下调试
【Java安全】ysoserial-URLDNS链分析_第21张图片最后将(String)http的hash值经过一系列的运算赋值给h。
【Java安全】ysoserial-URLDNS链分析_第22张图片继续跟进,调用了getHostAdress方法
【Java安全】ysoserial-URLDNS链分析_第23张图片查看getHostAdress,先后调用getHost()、getByName()两个方法,最终是通过getByName(getHost())去发送dnslog请求
【Java安全】ysoserial-URLDNS链分析_第24张图片 分析到这里,dnslog就接收到了请求信息

结论

因为HashMap实现了Serializable接口,重写了readObject方法,导致在接下来调用hashCode时,能够成功通过hashCode()方法,一步一步调用URL.getHostAddress,进而发起远程请求触发dnslog。

你可能感兴趣的:(代码审计,java,安全,开发语言,安全架构,web安全)