Java's Object cloning mechanism allows an attacker to manufacture new instances of a class, without executing its constructor. The new instances are made by copying the memory images of existing objects. Although this is sometimes an acceptable way of creating new objects, it often is not. By misusing the clone feature, an attacker can manufacture multiple instances of a singleton class, create serious thread-safety issues by subclassing and cloning the subclass, bypass security checks within the constructor and violate the invariants of critical data.
Noncompliant Code Example
Consider the following noncompliant class definition. Unless someone knows the secret password, objects cannot be created. This is because the constructor for the class checks the input against the expected password before allowing object construction. It also performs a security check. The calling code uses a doPrivileged
block to create an instance of SensitiveClass
. Object creation beyond this block is prohibited by the security manager. However, since the SensitiveClass
advertises a public
clone()
method, it is possible to circumvent this restriction. This clearly violates the principle of least privilege. Yet another blemish is the inconsistent security checking.
class SensitiveClass implements Cloneable { protected SensitiveClass(String passwd) { // perform security manager check System.out.println("SensitiveClass construction done!"); } protected void use(){ System.out.println("In method use()"); } public SensitiveClass Clone() { // well-behaved clone() method SensitiveClass s = null; try { s = (SensitiveClass)super.clone(); }catch(Exception e) { System.out.println("not cloneable"); } return s; } } class Foo { protected void privileged() { final SensitiveClass sc[] = new SensitiveClass[2]; AccessController.doPrivileged(new PrivilegedAction() { public Object run() { sc[0] = new SensitiveClass("password"); // object creation with the password sc[0].use(); //allowed return null; } }); sc[1] = sc[0].Clone(); // object creation without the password sc[0].use(); // this should not be allowed } public static void main(String[] args) { Foo f = new Foo(); f.privileged(); } }
Compliant Solution
Sensitive classes should not implement the Cloneable
interface. If the class extends from a superclass that implements Cloneable
(and is therefore cloneable), it's clone()
method should throw a CloneNotSupportedException
. This exception must be caught and handled by the client code.
public SensitiveClass Clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); }
It is also required to declare SensitiveClass
final
so as to avoid malicious subclassing. This will stop an artful attacker from subclassing the sensitive class and creating several copies of the subclass, with the intention of introducing thread-safety issues.
Risk Assessment
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
MSC05-J |
medium |
probable |
medium |
P8 |
L2 |
References
[[Mcgraw 98]]
[[Wheeler 03]] 10.6. Java
[[MITRE 09]] CWE ID 498 "Information Leak through Class Cloning", CWE ID 491 "Public cloneable() Method Without Final (aka 'Object Hijack')"
MSC04-J. Be aware of JVM Monitoring and Managing 49. Miscellaneous (MSC) MSC30-J. Generate truly random numbers