职位结构:


情境

代码和输出
附加信息/评论


1。
情境
鉴于我可以编辑(可序列化类的)(私有嵌套)SerializedProxy的序列化字节流,以打破SerializedProxy本身的不变性,因此,我可以更改正在反序列化的实例。

在这种情况下,我可以访问SerializedProxy类的序列化形式,而无需在readResolve()中强制不变式的情况下,对要序列化的类的字节流攻击同样容易。

2.问题

串行化代理方法的所谓安全性-字节流攻击-是否纯粹基于这样的假设:攻击者始终无法获得序列化形式的内容或SerializedProxy的源代码?如果不是,我是否误解或错过了实施的某些部分?

3.代码
(注意:Serializer是将序列化对象写入文件的util类。)

3.1使用值5序列化代理。

    import java.io.Serializable;
    import java.io.InvalidObjectException;
    import java.io.IOException;
    import java.io.ObjectOutputStream;
    public class SerializationProxyTest implements Serializable
    {
        final int id;

        private SerializationProxyTest(int val)
        {
            id = val;
        }

        private void writeObject() throws InvalidObjectException, IOException
        {
            throw new InvalidObjectException("Invalid object called for Serialization: proxy not found.");
        }


        private Object writeReplace()
        {
            System.out.println("writeReplace 1 ");
            return new SerializationProxy(this);

        }

        private static class SerializationProxy implements Serializable
        {
            final int id;

            SerializationProxy(SerializationProxyTest obj)
            {
                this.id = obj.id;
            }

            /* private void writeObject(ObjectOutputStream oos) throws IOException
            {

                oos.defaultWriteObject();

            } */

            private Object readResolve()
            {
                System.out.println("readResolve step 1 ");
                return new SerializationProxyTest(this.id);
                // return "Something Else!";

            }
        }

        public static void main(String[] args) throws IOException, ClassNotFoundException
        {

            Serializer.serializeObject(new SerializationProxyTest(5));

            SerializationProxyTest spt = (SerializationProxyTest) Serializer.deserializeObject("/home/code/java/serialized_proxy_class.ser");

            System.out.println("stored variable is:  " + spt.id);
        }
    }


3.1输出:


   [java]$ java SerializationProxyTest
            writeReplace 1
            readResolve 1
            object is: SerializationProxyTest@4eec7777
            stored variable is:  5


最高价0005 7372 0029 5365 7269 616c 697a
6174 696f 6e50 726f 7879 5465 7374 2453
6572 6961 6c69 7a61 7469 6f6e 5072 6f78
793b 8ab7 89f9 dd6d aa02 0001 4900 0269
6478 7000 0000 05


3.2更改序列化的SerializedProxy将变量的值更改为6。


最高价0005 7372 0029 5365 7269 616c 697a
6174 696f 6e50 726f 7879 5465 7374 2453
6572 6961 6c69 7a61 7469 6f6e 5072 6f78
793b 8ab7 89f9 dd6d aa02 0001 4900 0269
6478 7000 0000 06


3.3通过反序列化更改后的SerializedProxy来初始化Serializable类:SerializationProxyTest类用6而不是5初始化。

                SerializationProxyTest spt = (SerializationProxyTest) Serializer.deserializeObject("/home/code/java/serialized_proxy_class.ser");

            System.out.println("stored variable is:  " + spt.id);

        [java]$ java SerializationProxyTest
    writeReplace 1
    readResolve 1
    object is: SerializationProxyTest@4eec7777
    stored variable is:  6


4.其他信息/评论:假设SerializedProxy方法具有某些固有的“安全性”,只是出于阅读“有效Java”而产生的好奇心。这里做出的另一个假设是,即使不了解类结构,攻击者也可以通过反复试验对字节流进行有效的更改。

最佳答案

反序列化时,串行代理必须强制执行与构造函数相同的不变式(如果要使用该路由,则强制采用静态创建方法的不变式)。这通常是通过使用公共构造函数(或方法)创建真实对象的串行代理来实现的。

在问题的代码中,id始终为5的不变式在静态创建方法(main)中。串行代理代码不使用它。

注意:您的SerializationProxyTest是子类的。 Java字节码不需要类具有构造函数,因此基类不必具有可访问的构造函数。通常,您此类中的所有非最终公共方法或受保护方法都是可以重写的。

另请注意,第3版有效Java的序列化一章中有更正-请勿使用早期版本。

关于java - 对SerializationProxy的字节流攻击:更安全吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58028028/

10-11 04:20