ysoserial之URLDNS - P1
ysoserial
官方Description
ysoserial is a collection of utilities and property-oriented programming “gadget chains” discovered in common java libraries that can, under the right conditions, exploit Java applications performing unsafe deserialization of objects. The main driver program takes a user-specified command and wraps it in the user-specified gadget chain, then serializes these objects to stdout. When an application with the required gadgets on the classpath unsafely deserializes this data, the chain will automatically be invoked and cause the command to be executed on the application host.
简单理解为ysoserial集成了Java反序列漏洞的gadget(利用链), 在利用Java反序列化漏洞时可直接通过ysoserial对目标站点环境进行定制化POC/EXP生成。其中包括但不限于cc(Apache Commons Collections)1-7;
实例分析
本文将作为笔者学习Java反序列化漏洞的Part 1, ysoserial中的URLDNS可用于漏洞探测, 当目标站点存在反序列化漏洞时可使用此gadget发起DNS查询。因为URLDNS不依赖第三方包, 所以只要Java应用存在反序列化漏洞便可用此探测。
调用栈如下所示:
HashMap readObject() ->
hash(key) ->
key.hashCode() ->
URL.hashCode() ->
URLStreamHandler.hashCode() ->
getHostAddress(u) ->
java.net.InetAddress.getByName(host) 最终发起DNS请求
首先来到HashMap的readObject方法, 在1405行处调用了putVal方法, 传入的第一个参数调用了hash方法, 跟进查看:
hashCode默认为-1, 调用handler.hashCode(this)方法并传入了自身引用, handler为URLStreamHandler对象。
在URLStreamHandler对象hashCode方法中调用了getHostAddress方法
在getHostAddress中又调用了java.net.InetAddress.getByName()方法发起用于获取IP的DNS查询:
回到刚开始的第一步, 如何得知key为java.net.URL呢?亦或者说我们如何让key为URL对象才可以利用, 在readObject方法中可以看到:
找到序列化方法:
在internalWriteEntries方法里循环tab变量再写入对象输出流中, 而tab引用的是HashMap的成员变量table
。
回溯一下table成员变量, 在put方法中接收了泛型的key, value参数。然后调用putVal方法, 在628行处调用了resize方法
在resize中table引用了newTab变量, 而newTab指向Node对象:
现在能够知道table其实就是HashMap$Node(内部静态类), 不过此时的table是没有任何元素的。
此时继续向下执行705行的if条件不成立直接return newTab, 回到putVal方法, 在630行处调用newNode方法实例化Node:
赋值后再看table
可自行使用如下代码调试:
1 | public class URLDNS { |
序列化实现
1 | public class URLDNS { |