首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JAVA反序列化链URLDNS分析

JAVA反序列化链URLDNS分析

作者头像
yulate
发布2023-05-02 10:58:00
发布2023-05-02 10:58:00
92600
代码可运行
举报
运行总次数:0
代码可运行

本文最后更新于 419 天前,其中的信息可能已经有所发展或是发生改变。

一、简介

URLDNS这条链,并不能用来执行其他命令来RCE,只能用来发送一次DNS请求到我们指定的网站上,然后我们就能查看是否有请求记录而来判断是否存在Java的反序列化漏洞。简短的来说:URLDNS只能用来探测和验证是否存在漏洞。看似没什么用,但其实在渗透测试的实战中,这种用DNS请求来探测和验证漏洞的点到为止的思想还是挺常用的。而且这个Gadget还不需要任何其他的依赖,原生Java就能够成功调用成功。

二、流程分析

如上文所述,此Gadget不需要其他的以来,所以直接创建一个Java项目来进行测试。

为了方便的进行分析可以从github上下载ysoserial的源码来辅助理解此Gadget

frohoff/ysoserial: A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization. (github.com)

1、基础理论

文件定位:ysoserial-master\src\main\java\ysoserial\payloads\URLDNS.java

部分payload如下:

代码语言:javascript
代码运行次数:0
运行
复制
HashMap ht = new HashMap(); // HashMap that will contain the URL
URL u = new URL(null, url, handler); // URL to use as the Key
ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.

注释中的Gadget调用顺序如下:

代码语言:javascript
代码运行次数:0
运行
复制
    Gadget Chain:
      HashMap.readObject()
        HashMap.putVal()
          HashMap.hash()
            URL.hashCode()

在正式的调试阅读源代码前,我们需要理解HashMap的大致原理

HashMap是一种为提升操作效率的数据结构,本质在使用上还是存取key-value键值对的使用方式,但是在实现上引入了key值的HASH映射到一维数组的形式来实现,再进入了链表来解决hash碰撞问题(不同的key映射到数组同一位置)。

从键值对的设置和读取两方面来解释:

设置新键值对 key-value:

  1. 计算key的hash:Hash(k)
  2. 通过Hash(k)映射到有限的数组a的位置i
  3. 在a[i]的位置存入value
  4. 因为把计算出来的不同的key的hash映射到有限的数组长度,肯定会出现不同的key对应同一个数组位置i的情况。如果发现a[i]已经有了其他key的value,就放入这个i位置后面对应的链表(根据多少的情况可能变为树)中。

读取key的value:

  1. 计算key的hash:Hash(k)
  2. 通过Hash(k)映射到有限的数组a的位置i
  3. 读取在a[i]的位置的value
  4. 如果发现a[i]已经有了其他key的value,就遍历这个i位置后面对应的链表(根据多少的情况可能变为树)去查找这个key再去取值。
2、断点调试

在了解了HashMap之后开始进行断点调试,在ht.put(u, url);处打上断点。

Edit configurations中设置好参数,debug运行入口函数。

首先ht对象的类为HashMap,其中存在有反序列化入口readObject()

readObject()中在最后调用了putVal()方法来进行了一次hash计算

回到断点出跟进putVal()方法,可以看见keyvalue两个参数中都是传入我们设置的DNSLOG地址

继续跟入hash()方法中

hash()方法中传入的key肯定不会为null,会执行key.hashCode(),跟入其中

这里的handlerURLStreamHandler的对象,hashCode的值默认设置成了-1,所以直接调用了handler.hashCode()方法并重新赋值了hashCode并返回,继续跟进

getProtocol()方法会返回传入的协议,如http

在获取到协议后经过一次if判断后将protocol经过hashCode()方法计算后的返回值加到了h中,跟入hashCode()方法中

这里的hashCode()String中的方法,在进行了一系列的操作后将传入stringhash值返回回去。

继续往下调用了getHostAddress()方法

getHostAddress()中先后调用了getHost()getByName()两个方法,最终触发dnslog的位置即为getByName(getHost())来进行发送请求。

getByName()会根据host来确定主机名称的IP地址,这肯定会触发DNS请求。

最终调用链如下:

代码语言:javascript
代码运行次数:0
运行
复制
HashMap.readObject() => HashMap.putVal() => HashMap.hash() => URL.hashCode() =>
URLStreamHandler.hashCode() => URLStreamHandler.hashCode().getHostAddress => URLStreamHandler.hashCode().getHostAddress.InetAddress.getByName()

三、URLDNS链使用

将生成的序列化payload保存在一个txt里,后面用一个测试demo读取文件数据再给他反序列化一下,观察dnslog请求就可以了。

代码语言:javascript
代码运行次数:0
运行
复制
java -jar ysoserial.jar URLDNS "http://ba0i6v.dnslog.cn" 
java -jar ysoserial.jar URLDNS "http://ba0i6v.dnslog.cn" > URLDNS.txt

反序列化测试demo

代码语言:javascript
代码运行次数:0
运行
复制
package ysoserial.test;

import java.io.FileInputStream;
import java.io.ObjectInputStream;

public class URLDNSTestDemo {
    public static void main(String[] args) throws Exception {

        FileInputStream fis = new FileInputStream("D:\\aq\\jarTools\\URLDNS.txt");
        ObjectInputStream objectInputStream = new ObjectInputStream(fis);
        objectInputStream.readObject();
    }
}

运行一下demo

成功在DNSlog获取到记录

浏览量: 204

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-3-04 1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、简介
  • 二、流程分析
    • 1、基础理论
    • 2、断点调试
  • 三、URLDNS链使用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档