...
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 | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
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 | Likely | High | P9 | L2 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
Useful for developing exploits that detect violation of this rule |
Related Guidelines
Bibliography
...