【Java安全】ysoserial-URLDNS链分析

打印 上一主题 下一主题

主题 819|帖子 819|积分 2457

前言

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

   下载ysoserialhttps://github.com/frohoff/ysoserial项目源码,导入IDEA,并在pom.xml中搜刮mainclass,寻找程序的入口点
  

   在程序运行之前,先设置两个参数(URLDNS “http://xxxx.dnslog.cn”),否则运行IDEA会报错。
  

   简单分析一下 GeneratePayload 的main方法,首先会判断是否传入两个参数, 假如不是则打印帮助信息
,是的话则对两个参数依次赋值为payloadType和command。接着实例化一个payloadClass对象,跟进一下getPayloadClass方法
  

   getPayloadClass会返回一个反射的class对象,该class对象为GeneratePayload的class对象的包名+字符串“payloads”+我们传入的第一个参数className(也就是payloadType)
  

   对应ysoserial中写好的URLDNS脚本,也就是说,我们传入的第一个参数是找到ysoerial的payload脚本。
  

   后续会实例化payloadClass,并调用getObject方法,传入我们传入的第二个参数command。跟进getObject方法中,分析传入command后,程序是如那边理的。
  

   发现终极会跳转到URLDNS中
  

   那么以上操作就是根据传入的参数,定位到利用链的类文件中,调用该类的 getObject方法,天生并返回paylaod。
URLDNS类我们先放到一边,继续分析 GeneratePayload 中的main方法。
  

   之后会调用 serialize方法,将URLDNS类中返回的值(天生的payload)序列化并打印输出。
  

URLDNS链分析

   URLDNS为Java的原生类,利用结果只是触发一次DNS哀求,并不会命令执行,实用于验证是否存在反序列化漏洞。
在URLDNS.java中,作者已经给出了Gadget chain
  

   我们先看第53行代码,首先声明了一个URLStreamHandler类,由于URLStreamHandler是个抽象类,不能够被实例化,因此创建了个URLStreamHandler的子类SilentURLStreamHandler。并实现父类URLStreamHandler的抽象方法openConnection。
  

   但为什么要重写getHostAddress方法呢,其实我们运用最简单粗暴的方法,将重写方法注释掉,对比没注释之前,有啥区别:区别在于,重写getHostAddress,在我们利用ysoserial天生payload时,不会触发payload,DNSLOG吸收不到哀求。即由于方法直接返回为Null,不会哀求我们的hostAddress
  

   而且在URL.java中,handler被transient关键字修饰,在序列化对象的时间,handler属性不会被序列化。意味着重写的方法并不会带进我们的payload中,这样我们在触发反序列化漏洞时,getHostAddress并没有被重写,能够正常哀求我们的网址。这也是我以为很精妙的一个地方。
  

   然后检察HashMap类,发现HashMap实现了Serializable序列化接口
  

   重写了readObject方法
  

   在重写的readObject方法中,有调用putVal方法举行一个hash计算
  

   调试,跟进putVal方法, 参数key和value都为输入的dnslog地址
  

   继续跟进,这里注意(标重点),调用的是key.hashCode(),即HashMap的参数u,顺利的从HashMap.hash()跳转到URL.hashCode()。
  

   这里hashCode()方法会对hashCode属性重新赋值
  

   这里调用了 URLStreamHandler 类的hashCode方法,参数(URL)u为传入的DNSLOG地址
  

   通过getProtocol方法,获取 协议类型——http
  

   接下来这里举行一个if判断,h的值会加上portocal的hashCode()方法的返回值,跟进protocol.hashCode()方法
  

   继续往下调试
  

   最后将(String)http的hash值经过一系列的运算赋值给h。
  

   继续跟进,调用了getHostAdress方法
  

   检察getHostAdress,先后调用getHost()、getByName()两个方法,终极是通过getByName(getHost())去发送dnslog哀求
  

   分析到这里,dnslog就吸收到了哀求信息
  结论

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张国伟

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表