Hi!

I hope this is the correct mailing list, if not please tell me.

I was looking into using a ObjectInputFilter and try to improve the
security in some old code that uses serialization. After reading and
testing a bit I think the filtering works a bit strange and that it
does not provide enough information.

I have added a small test program below that I think illustrates the
problem. Running this on java 11 or java 13 gives the same result. The
program writes a small data structure to a an ObjectOutputStream and
then reads it in again, just to see what we get from the
ObjectInputFilter.

Output of example program:
roberto@roberto-d4:~/src/java$ ~/pkg/java/jdk-13.0.1+9/bin/java 
SerializationTest
Depth: 1, class: class Payload, array: -1
Depth: 2, class: class java.util.ArrayList, array: -1
Depth: 2, class: class [Ljava.lang.Object;, array: 2
Depth: 3, class: class X, array: -1
Depth: 3, class: null, array: -1

Problems:
1) It is not possible to filter long strings. So even when using
   a filter a long string will lead to OutOfMemoryError. The
   javadoc for ObjectInputFilter clearly states that this is how
   it is supposed to work. My thoughts are that I ought to be
   able to reject too long strings, at least TC_LONGSTRING that
   have an 8 byte length if I understand how ObjectInputStream
   works internally.

2) I do not understand how the depth is supposed to work in the
   example program. I get depth 2 for both the ArrayList and its
   contained Object[]. My expectations is that I ought to get the
   array at depth 3. Is depth 2 how it is supposed to work?

Do you have any clarification how should I think regarding the
ObjectInputFilter?

Thanks!
/robo

----------------------------------------------------------------------
import java.io.*;
import java.util.*;

class SerializationTest {
    public static void main(String[] args)
        throws IOException, ReflectiveOperationException {
        Payload p = new Payload ();
        byte[] data;
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream ();
             ObjectOutputStream os = new ObjectOutputStream (baos)) {
            os.writeObject (p);
            data = baos.toByteArray ();
        }
        try (ByteArrayInputStream bais = new ByteArrayInputStream (data);
             ObjectInputStream is = new ObjectInputStream (bais)) {
            is.setObjectInputFilter (SerializationTest::logInput);
            Payload pp = (Payload)is.readObject ();
        }
    }

    private static ObjectInputFilter.Status
        logInput (ObjectInputFilter.FilterInfo info) {
        System.out.println ("Depth: " + info.depth () +
                            ", class: " + info.serialClass () +
                            ", array: " + info.arrayLength ());
        return ObjectInputFilter.Status.ALLOWED;
    }
}

class Payload implements Serializable {
    List<X> ls;

    public Payload () {
        ls = new ArrayList<> ();
        ls.add (new X ("one"));
        ls.add (new X ("two"));
    }
}

class X implements Serializable {
    String x;
    public X (String x) {
        this.x = x;
    }
}
----------------------------------------------------------------------

Reply via email to