Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added a remark addressing OBJ09-J.

...

Code Block
bgColor#ccccff
languagejava
import java.io.*;
import java.util.*;

class WhitelistedObjectInputStream extends ObjectInputStream {
  public Set whitelist;

  public WhitelistedObjectInputStream(InputStream inputStream, Set wl) throws IOException {
    super(inputStream);
    whitelist = wl;
  }
 
  @Override
  protected Class<?> resolveClass(ObjectStreamClass cls) throws IOException, ClassNotFoundException {
    if (!whitelist.contains(cls.getName())) {
      throw new InvalidClassException("Unexpected serialized class", cls.getName());
    }
    return super.resolveClass(cls);
  }
}
 
class DeserializeExample {
  private static Object deserialize(byte[] buffer) throws IOException, ClassNotFoundException {
    Object ret = null;
    Set whitelist = new HashSet<String>(Arrays.asList(new String[]{"GoodClass1","GoodClass2"}));
    try (ByteArrayInputStream bais = new ByteArrayInputStream(buffer)) {
      try (WhitelistedObjectInputStream ois = new WhitelistedObjectInputStream(bais, whitelist)) {
        ret = ois.readObject();
      }
    }
    return ret;
  }
}

It might appear that the above compliant solution violates Rule OBJ09-J. Compare classes and not class names.  However, the security issue addressed by OBJ-09J is applicable only when comparing the class of an object that might have been loaded by a foreign ClassLoader, i.e., an object x for which it cannot be guaranteed that x.getClass()==Class.forName(x.getClass().getName()).  In WhitelistedObjectInputStream.resolveClass (which is the method that does the comparison of class names), a check could be added to verify that the return value (let's call it "ret") is such that ret == Class.forName(ret.getName()), but this check would always succeed, so it is pointless to add.

(On a somewhat related point, it may be noted that ObjectInputStream.resolveClass compares the serialVersionUID from the serialized data to the serialVersionUID of the Class object that it is going to return; if there is a mismatch, it throws an exception.)

Exceptions

SER12-EX0: Serialized data from a trusted input source does not require validation, provided that the code clearly documents that it relies on the input source being trustworthy.  For example, if a library is being audited, a routine of that library may have a documented precondition that its callers pre-validate any passed-in serialized data or confirm the input source as trustworthy.

...