Depth and String handling in ObjectInputFilter
Robert Olofsson
robert.olofsson at digpro.se
Fri Jan 17 15:26:25 UTC 2020
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 at 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;
}
}
----------------------------------------------------------------------
More information about the core-libs-dev
mailing list