Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

If it is convenient for a serializable class to perform operations with potentially dangerous side effects during deserialization, it should require that the programmer expressly whitelist

Non-Compliant Code Example

The class OpenedFile in the below noncompliant example opens a file during deserialization.  Operating systems typically impose a limit on the number of open file handles per process, and this limit is typically is not very large (e.g., 1024).  Consequently, deserializing a list of OpenedFile objects can exhaust the process's available file handles and cause the program to malfunction.

Code Block
bgColor#FFcccc
languagejava
import java.io.*;

class OpenedFile implements Serializable {
    public String filename;
    public BufferedReader reader;

    public OpenedFile(String _filename) {
        filename = _filename;
        init();
    }
    private void init() {
        try {
            reader = new BufferedReader(new FileReader(filename));
        } catch (FileNotFoundException e) { }
    }
    
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.writeUTF(filename);
    }

    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        filename = in.readUTF();
        init();
    }
} 

 

Compliant Solution

In the below compliant solution, the readObject method throws an exception unless the potentially dangerous class is whitelisted.

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

interface Whitelist {
    public boolean has(String className);
}
class WhitelistedObjectInputStream extends ObjectInputStream {
    Whitelist whitelist;
    public WhitelistedObjectInputStream(InputStream inputStream) throws IOException {
        super(inputStream);
    }
    public void setWhitelist(Whitelist wl) {
        whitelist = wl;
    }
}
class OpenedFile implements Serializable {
    public String filename;
    public BufferedReader reader;
    public OpenedFile(String _filename) {
        filename = _filename;
        init();
    }
    private void init() {
        try {
            reader = new BufferedReader(new FileReader(filename));
        } catch (FileNotFoundException e) { }
    }
    
    private void writeObject(ObjectOutputStream out) throws IOException {
        out.writeUTF(filename);
    }
    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        if (!(in instanceof WhitelistedObjectInputStream) || 
            !((WhitelistedObjectInputStream) in).whitelist.has(this.getClass().getName())) 
        {
            throw new SecurityException("Attempted to deserialize unexpected class.");
        }
        filename = in.readUTF();
        init();
    }
}

Risk Assessment

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

SER13-J

High

LikelyHighP9L2

Automated Detection

Tool
Version
Checker
Description

ysoserial

  Useful for developing exploits that detect violation of this rule

 

Related Guidelines

MITRE CWE

CWE-502, Deserialization of Untrusted Data

Bibliography

 

...