As is typical with security, it's important to set out the context this applies to. We're interested in cases where potentially malicious code can access the attacked trusted class. For instance within the browser Java PlugIn trusted libraries can be accessed by untrusted code. It used to be the case that RMI loaded remote code, however it has now fallen into line with policy of secure by default.
The issue with mutable arguments is that they can be changed between the time they are checked for validity and they are used. This is known as a Time Of Check/Time Of Use vulnerability, TOCTOU (or TOC2TOU). In practice, this can be two uses rather than one use specifically being a check. Other badly designed classes that appear immutable but are subclassable (for instance java.io.File
), can be subclassed to be mutable as part of their ability to execute arbitrary code when invoked.
The specific attack scenario being discussed here is where the clone
is overridden to to thwart the attempt at copying. The reference to a static
is irrelevant in this context (it's important in finalizer
attacks, but mostly reflects that attack code is rarely designed to be clean).
class MaliciousDate {
private final List<MaliciousDate> dates;
public MaliciousDate(List<MaliciousDate> dates) {
this.dates = dates;
}
@Override public MaliciousDate clone() {
MalicousDate other = (MalicousDate)super.clone(); // Or new MalicousDate
synchronized (dates) {
dates.add(other);
}
return other; // Or return this;
}
}
To modify the example from the book.
public Period(Date start, Date end) {
// Failing defensive copy.
start = (Date)start.clone();
end = (Date)end .clone();
if (start.compareTo(end) > 0)
throw new IllegalArgumentExcpetion();
this.start = start;
this.end = end;
}
Then attack with:
List<MaliciousDate> dates = new ArrayList<>()
Date start = new MaliciousDate(dates);
Date end = new MaliciousDate(dates);
Period p = new Period(start, end);
dates.get(1).setYear(78); // Modifies internals of p!
Conclusion: Make your value types robustly immutable. More information in the completely awesome Secure Coding Guidelines for the Java Programming Language.
clone
? And if a SecurityManager is installed getDeclaredFields will throw a SecurityException (unless explicitly allowed). – Aeromechanic