Recall that immutability offers several benefits such as thread-safety, prevention against inadvertent modification of fields and malicious tampering. Class invariants and state are always consistent with the requirements and no defensive copying is necessary. Sometimes however, it is not possible to make sensitive classes immutable. Fortunately, there is a mechanism that allows code to expose mutable classes to untrusted code by granting read-only access. This is largely achieved through unmodifiable wrappers. One example is of the Collection
classes wherein a set of wrappers allow clients to observe an unmodifiable view of the particular Collection
object.
Noncompliant Code Example
This noncompliant code example consists of class Modifiable
which allows the internal ArrayList
object to be modified. An untrusted invoker may call the mutator method listIt()
and violate the object's immutability property.
class Modifiable { private List<Integer> l = new ArrayList<Integer>(); public void listIt() { doSomething(l); // ... } private void doSomething(Collection<Integer> collection) { collection.add(1); } }
Compliant Solution
This compliant solution recommends an unmodifiable wrapper to shield the mutator method(s) and provide an unmodifiable view to the caller. Internally, the unmodifiable Collection
's mutator methods are designed to throw an UnsupportedOperationException
in such events.
// ... doSomething(Collections.unmodifiableCollection(list)); private void doSomething(Collection<Integer> collection) { collection.add(1); // throws java.lang.UnsupportedOperationException }
It should be noted that objects present within the Collection
may not be thread-safe. Consider for example, an ArrayList
of ArrayLists
wherein the contained ArrayList
is still susceptible to modification.
Noncompliant Code Example
This noncompliant example shows an interface MutableInterface
which declares an accessor method and a mutator method. This class does not expose an unmodifiable view to implementing clients.
interface MutableInterface { int[] getArray(); // accessor void setArray(int[] i); //mutator } class SensitiveMutable implements MutableInterface { int[] array = new int[10]; // mutable array public int[] getArray() { return array.clone(); } public void setArray(int[] i) { array = i; } }
Compliant Solution
In general, sensitive classes can can be transformed into safe-view objects by implementing all the methods defined by the core interface, including the mutator methods. In this case, the difference is that the mutators need to throw an UnsupportedOperationException
so that clients cannot carry out operations that affect the immutability of the object.
In this solution, an UnmodifiableSensitiveMutable
is constructed by extending SensitiveMutable
. An interface UnmodifiableInterface
consists of the method unmodifiableView()
which accepts a SensitiveMutable
object as the sole parameter. It returns an equivalent object that is a subtype of the same class, and which is unmodifiable. An exception is thrown if the caller attempts to use the mutator method on the returned object. This object can be passed to untrusted code as required.
interface UnmodifiableInterface { SensitiveMutable unmodifiableView(SensitiveMutable sm); } class UnmodifiableSensitiveMutable extends SensitiveMutable { int[] array = new int[10]; public void setArray(int[] i) { throw new UnsupportedOperationException(); } } class UnmodifiableWrapper extends UnmodifiableSensitiveMutable implements UnmodifiableInterface { public SensitiveMutable unmodifiableView(SensitiveMutable sm) { return new UnmodifiableWrapper(); // subtype of SensitiveMutable } } class Invoker { public static void main(String[] args) { UnmodifiableWrapper uw = new UnmodifiableWrapper(); SensitiveMutable s = uw.unmodifiableView(sm); s.setArray(new int[10]); // throws UnsupportedOperationException unlike s.getArray() } }
Risk Assessment
Failure to provide an unmodifiable safe-view of sensitive mutable objects to untrusted code can lead to malicious tampering and corruption of the object.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
SEC01-J |
medium |
probable |
high |
P4 |
L3 |
Automated Detection
TODO
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[Tutorials 08]] Unmodifiable Wrappers
01. Platform Security (SEC) 07. Object Orientation (OBJ) SEC02-J. Do not expose standard APIs that may bypass Security Manager checks to untrusted code