You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

Deserializing untrusted data can cause Java to create an object of an arbitrary attacked-specified class, provided that the class is available on the classpath specified for the JVM.  Some classes have triggers that execute additional code when they are created in this manner.  If such classes are poorly designed, such code could even call to Runtime.exec with an attacker-supplied argument.  Therefore, untrusted input to be deserialized should be validated to ensure that the serialized data contains only classes from a whitelist of expected classes.  This can be done by overloading the resolveClass method of the ObjectInputStream class.

 

Non-Compliant Solution

class DeserializeExample {
    public static Object deserialize(byte[] buffer) throws IOException, ClassNotFoundException {
        Object ret = null;
        try (ByteArrayInputStream bais = new ByteArrayInputStream(buffer)) {
            try (ObjectInputStream ois = new ObjectInputStream(bais)) {
                ret = ois.readObject();
            }
        }
        return ret;
    }
} 

 

Compliant Solution

This compliant solution is based on http://www.ibm.com/developerworks/library/se-lookahead/ :

class LookAheadObjectInputStream extends ObjectInputStream {
    public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
        super(inputStream);
    }
    @Override
    protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
        switch (desc.getName()) {
            case "GoodClass1": break;
            case "GoodClass2": break;
            default:	
                throw new InvalidClassException("Unexpected serialized class", desc.getName());
        }
        return super.resolveClass(desc);
    }
}

class DeserializeExample {
    private static Object deserialize(byte[] buffer) throws IOException, ClassNotFoundException {
        Object ret = null;
        try (ByteArrayInputStream bais = new ByteArrayInputStream(buffer)) {
            try (LookAheadObjectInputStream ois = new LookAheadObjectInputStream(bais)) {
                ret = ois.readObject();
            }
        }
        return ret;
    } 
}

 

Risk Assessment

Whether a violation of this rule is exploitable depends on what classes are on the JVM's classpath.  (Note that is a property of the execution environment, not of the code being audited.) In the worst case, it could lead to remote execution of arbitrary code.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

 

High

    

Automated Detection

No known tools for automated detection exist yet.  However, it should not to be hard to write a static analysis to check for deserialization that fails to overload resolveClass to compare against a whitelist.

Related Guidelines

MITRE CWE

CWE-502, Deserialization of Untrusted Data

Bibliography

http://www.ibm.com/developerworks/library/se-lookahead/

  • No labels