java url dns_Yso中的URLDNS分析学习

作为 ysoserial 中最简单链,这里简单记录学习一下

首先使用ysoserial生成urldns的探测类型

首先先去 dnslog.cn 获取一个url

ab4d67d4c07e40521eb9f0f34709e6d7.png

java -jar ysoserial-0.0.6-SNAPSHOT-all.jar URLDNS "http://pk3q64.dnslog.cn" > Test.txt

查看生成的文件

c37cadbc0027356679d08dcb80e74dfe.png

349d353429eae9bb0db9d83fd55fddfc.png

Java反序列化后的前几个字节就是 ac ed

这其实是一个序列化后的对象,这里我们将它反序列化看一下

我们将这个反序列化了一下

随即我们就收到了DNS查询的记录

9cb610f531999df57361a071e0034d0e.png

这是为什么呢

接下来分析一下

简单的观察一下ysoserial

我们刚才生成一个Payload使用的是类似于 java -jar ysoserial-0.0.6-SNAPSHOT-all.jar URLDNS "http://pk3q64.dnslog.cn" > Test.txt 的命令

我们分析一下干了什么吧

首先下载 ysoserial 项目

https://github.com/frohoff/ysoserial

生成Payload的类在 GeneratePayload.java

bbd1f3d0ac51e2ea5b18be800730e3e4.png

首先检查我们传入的参数是否正确,然后将我们调用的payload放入 payloadType,参数放入 command 例如上文我们调用的是 URLDNS 参数是我们的url

5bb748211bc38524733ee41446f064c5.png

之后将我们的payload传入 Utils.getPayloadClass 中,这个是作者自己实现的一个工具类,我们传入payload,根据反射获取到类的 Class ,然后判断是否为空

其中Payload都放在 payloads 文件夹下

d581395430c5967d8486f447352eb608.png

我们这里面调用的就是 URLDNS 了

91ddc63da59fd8a5f3d1c6814d3300c5.png

之后根据 Class 获取到类的实例,然后向 getObject 方法中传入我们的参数,将返回的对象序列化输出,我们后面用 > test.txt 就是把序列化的数据重定向到文件中

其中 getObject 的实现如下

16309494fda9eb190efd2cbc0aae213a.png

这个就是 ysoserial 的简单工作原理,其他的也类似

分析

DNSURL 反序列化的链为

首先序列化点在 HashMap的 readObject 方法(因为实现了Serializable接口)

549dc51910abc7e4706bf0d0134c4c68.png

readObject 调用了 putVal方法,且参数里调用了 HashMap的hash方法

a024fe253b020734b60719ec8dd9ef97.png

继续跟进

bcf981e09d79cff4857948a53c5d2233.png

因为HashMap里面的 key 与 Value 是一个对应的关系,所以看看 ysoserial传入的 key 是什么吧

4297ada9cd22997668286ae992ac53e1.png

显然传入的 key 是 URL 类

因此是调用了 URL 中的 hashCode方法,跟进看一下

0142474242085ace3d04ed31a784e055.png

若 hashcode 的值为 -1 则调用 handler.hashcode 方法

其实这个值默认就是 -1 的

24fbc70d45f1a4970aefd9cdfa99845c.png

yso中也是用反射将其强制设置为 -1

ce206c26a283e868296810381f1ada61.png

调用的 hander.hashCode 其实也就是我们传入的 hander

696dfbbe4bcb35768d4454b99ae5340d.png

在 URL 的构造方法中将其初始化为我们传入的

45a2ba1232c8e2f00292cddbbbf20124.png

ysoserial 中的 SilentURLStreamHandler 其实就是 URLStreamHandler 的子类(为了程序的健壮性,后面有解释)

所以 handler.hashCode(this) 其实就是调用的 URLStreamHandler.hashCode(this),我们跟进一下

c754e049fab956dd8bce6d5fdf978932.png

这里面将 u 传入 getHostAddress

跟进getHostAddress

044c09bc1164d9cebf6a0c8be4eff335.png

其中将 u.getHost() 的结果放入 InetAddress.getByName 此函数将是根据主机名获取对应ip,相当于发出一次dnslog请求

我们查看一下 URL.getHost()

d564e88c80db8810562c2c4441c4995d.png

返回的是 host,而这个值已经在我们初始化 URL 的时候就被设置了(设置为我们一开始传入的url)

因此一套简单的流程就出来了

后续思考

我们查看一下HashMap的 put 方法看看

e79f7af44a4705979de22320eef0580e.png

发现也调用了 hash方法

232b5f8fb1e5ecd85706839d0986604e.png

那这样我们利用 ysoserial 生成 POC的时候,也不是会有dns请求吗?

332bac0f4e32ca7338fb92d75bab5846.png

我们测试一下

43e8d3bbec50212dfe43305e9fead8f8.png

确实会产生很多请求

有个方法就是通过反射修改 hashCode的值(将URL的 hashCode修改为非 -1 就不会调用到了)

f8398eacb660bd3e8f45dad0e4946a12.png

那么 URLDNS 呢

d0d3ea4072f080d70411d7c7b32af219.png

也没有产生请求

原因在这个

4e8266dc25bf11f022d3a1fdf1ec287e.png

这个 SilentURLStreamHandler 继承了 URLStreamHandler

重写了里面的 openConnection 和 getHostAddress

273dd9f9e86f88b7fe887fd93e3c3cf9.png

因此在调用 put 方法的时候不会触发 dns 查询

那这样我们反序列化的时候不是也因为重写了方法而不能进行 dns 查询吗?

原因是因为 URL 里面的 handler 设置的是 transient

254fb9ad1644ad21e4c94b7b70952b47.png

因为transient修饰符无法被序列化,所以虽然它最后是没执行dns请求,但是在反序列化的时候还是会执行dns请求!

简单测试一下

User.java

bd9b89601c906415d1ec06fd8ac17880.png

可以看见 name 属性未被反序列化,还是原来的值(为赋值前 为 null)

总结

虽然 URLDNS 不能Getshell,但是可以帮助我们探测目标是否存在漏洞等,写POC或者扫描器的时候挺适用的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值