Java's Object cloning mechanism can allow allows an attacker to manufacture new instances of a class that has been defined , without executing its constructor. If a class is not cloneable, the attacker can define a subclass and make the subclass implement the java.lang.Cloneable interface. This lets the attacker create new instances of the class. The new instances of the class are made by copying the memory images of existing objects. Although this is sometimes an acceptable way of making a creating new objectobjects, 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 for the input against the password stored in some password fileexpected 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.
Code Block | ||
---|---|---|
| ||
class MyPrivacySensitiveClass { implements //define class member fieldsCloneable { //... public MyPrivacyprotected SensitiveClass(String passwd) { // perform security manager String actualPass;check System.out.println("SensitiveClass FileReader fr = new FileReader("Passfile.txt"construction done!"); } protected BufferedReader br = new BufferedReader(fr);void use(){ actualPass = br.readLine(); if(actualPass.equals(passwd)){ // return normally } else{ // exit the program, print an authentication error // preventing the class object from being created } } public void use(){ // } //... } |
The attacker can create a new instance of MyPrivacy class by using a cloneable subclass and bypass the constructor. Bypassing the constructor leads to bypassing the password check done in the constructor.
Code Block | ||
---|---|---|
| ||
class Test extends MyPrivacy implements Cloneable{ public static void somefunction(MyPrivacy obj) { System.out.println("In method use()"); } public SensitiveClass Clone() { // well-behaved clone() method SensitiveClass s = null; try { Test t s = (TestSensitiveClass)objsuper.clone() ; }catch(Exception e) { System.out.println("not cloneable"); } if (t != null) t.use(); // Another object instantiated without knowing the password..... } } |
Compliant Solution
Classes should be made noncloneable to prevent this from occurring. The following method may be implemented to achieve this.
Code Block | ||
---|---|---|
| ||
class MyPrivacyreturn s; } } class Foo { protected //define class member fields //...void privileged() { final SensitiveClass sc[] = new SensitiveClass[2]; public MyPrivacy(String passwdAccessController.doPrivileged(new PrivilegedAction() { public Object String actualPass;run() { FileReader frsc[0] = new FileReaderSensitiveClass("Passfile.txtpassword"); // object creation with BufferedReader br = new BufferedReader(fr);the password actualPass = br.readLinesc[0].use(); if(actualPass.equals(passwd)){//allowed return null; // return normally } }); else{ sc[1] = sc[0].Clone(); // exitobject thecreation program,without print an authentication errorthe password sc[0].use(); // preventingthis theshould classnot object from being createdbe allowed } public } public static void usemain(String[] args) { Foo // f = } //... public final void clone() throws java.lang.CloneNotSupportedException{new Foo(); throw new java.lang.CloneNotSupportedExceptionf.privileged(); } } |
Compliant Solution
One can also make a class nonsubclassable. This can be achieved by finalizing a class.
Code Block | ||
---|---|---|
| ||
 final class MyPrivacy {
// Rest of the definition remains the same
}
|
If it is absolutely required to make the class cloneable, even then protective measures can be taken.
...
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.
Code Block | ||
---|---|---|
| ||
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 |
...