...
In this noncompliant code example, security manager checks are used within the constructor but are omitted from the writeObject()
and readObject()
methods that are used in the serialization-deserialization process. This omission allows untrusted code to maliciously create instances of the class.
Code Block | ||
---|---|---|
| ||
public final class Hometown implements Serializable {
// Private internal state
private String town;
private static final String UNKNOWN = "UNKNOWN";
void performSecurityManagerCheck() throws AccessDeniedException {
// ...
}
void validateInput(String newCC) throws InvalidInputException {
// ...
}
public Hometown() {
performSecurityManagerCheck();
// Initialize town to default value
town = UNKNOWN;
}
// Allows callers to retrieve internal state
String getValue() {
performSecurityManagerCheck();
return town;
}
// Allows callers to modify (private) internal state
public void changeTown(String newTown) {
if (town.equals(newTown)) {
// No change
return;
} else {
performSecurityManagerCheck();
validateInput(newTown);
town = newTown;
}
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.writeObject(town);
}
private void readObject(ObjectInputStream in) throws IOException {
in.defaultReadObject();
// If the deserialized name does not match the default value normally
// created at construction time, duplicate the checks
if (!UNKNOWN.equals(town)) {
validateInput(town);
}
}
}
|
...
This compliant solution implements the required security manager checks in all constructors and methods that can either modify or retrieve internal state. Consequently, an attacker cannot create a modified instance of the object (using deserialization) or read the serialized byte stream to reveal serialized data.
Code Block | ||
---|---|---|
| ||
public final class Hometown implements Serializable {
// ... all methods the same except the following:
// writeObject() correctly enforces checks during serialization
private void writeObject(ObjectOutputStream out) throws IOException {
performSecurityManagerCheck();
out.writeObject(town);
}
// readObject() correctly enforces checks during deserialization
private void readObject(ObjectInputStream in) throws IOException {
in.defaultReadObject();
// If the deserialized name does not match the default value normally
// created at construction time, duplicate the checks
if (!UNKNOWN.equals(town)) {
performSecurityManagerCheck();
validateInput(town);
}
}
}
|
...
Secure Coding Guidelines for the Java Programming Language, Version 3.0 | Guideline 5-4. Duplicate the |
Android Implementation Details
The java.security
package exists on Android for compatibility purposes only and it should not be used.
Bibliography
Section 2.4, Serialization |
SER03-J. Do not serialize unencrypted, sensitive data 13. Serialization (SER)