Classes containing private, confidential, or otherwise sensitive data are best not copied. If a class is not meant to be copied, then failing to define copy mechanisms, such as a copy constructor, is insufficient to prevent copying.
Java's Object 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 rather than by executing the class's constructor. Often, this is sometimes an acceptable unacceptable way of creating new objects, it often is not. By misusing . An attacker can misuse the clone feature , an attacker can to 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.
Classes that have security checks in their constructors must beware of finalization attacks, as explained in OBJ11-J. Be wary of letting constructors throw exceptions.
Classes that are not sensitive but maintain other invariants must be sensitive to the possibility of malicious subclasses accessing or manipulating their data and possibly invalidating their invariants (see OBJ04-J. Provide mutable classes with copy functionality to safely allow passing instances to untrusted code for more information).
Noncompliant Code Example
This noncompliant example derives some functional behavior from the implementation of the class java.lang.StringBuffer
, prior to JDK v1.5. A SensitiveClass
class is defined code example defines class SensitiveClass
, which contains a character array used to internally hold a filenamefile name, and along with a Boolean
shared variable. When a client requests a String
instance by invoking the get()
method, the shared flag is set. Operations that can modify the array are subsequently prohibited to be consistent with the returned String
object. Consequently, the replace()
method designed to replace all elements of the array with an 'x', cannot execute normally when the flag is set. Java's cloning feature provides a way to illegally work around this constraint even though SensitiveClass
does not implement the Cloneable
interface.Here, a malicious class subclasses the non-final SensitiveClass
and provides a public
clone()
method. It proceeds to create its own instance (ms1
) and produces a second one (ms2
), by cloning the first. It subsequently obtains a new String
filename
object by invoking the get()
method on the first instance. At this point, the shared
flag is set to true
. Since the second instance (ms2
) does not have its shared flag set to true
, it is possible to alter the first instance ms1
using the replace()
method. This downplays any security efforts and severely violates the object's invariants., initialized to false. This data is not meant to be copied; consequently, SensitiveClass
lacks a copy constructor.
Code Block | ||
---|---|---|
| ||
class SensitiveClass { private char[] filename; private Boolean shared = false; protected SensitiveClass(String filename) { this.filename = filename.toCharArray(); } protectedfinal void replace() { if (!shared) { for(int i = 0;i<filename i < filename.length; i++) { filename[i]= 'x' ;} } } protectedfinal String get() { if (!shared) { shared = true; return String.valueOf(filename); } else { throw new ErrorIllegalStateException("ErrorFailed to gettingget instance"); } } protectedfinal void printFilename() { System.out.println(String.valueOf(filename)); } } |
When a client requests a String
instance by invoking the get()
method, the shared
flag is set. To maintain the array's consistency with the returned String
object, operations that can modify the array are subsequently prohibited. As a result, the replace()
method designed to replace all elements of the array with an x
cannot execute normally when the flag is set. Java's cloning feature provides a way to circumvent this constraint even though SensitiveClass
does not implement the Cloneable
interface.
This class can be exploited by a malicious class, shown in the following noncompliant code example, that subclasses the nonfinal SensitiveClass
and provides a public clone()
method:
Code Block | ||
---|---|---|
| ||
class MaliciousSubclass extends SensitiveClass implements Cloneable { protected MaliciousSubclass(String filename) { super(filename); } @Override public MaliciousSubclass Cloneclone() { // wellWell-behaved clone() method MaliciousSubclass s = null; try { s = (MaliciousSubclass)super.clone(); } catch(Exception e) { System.out.println("not cloneable"); } return s; } public static void main(String[] args) { MaliciousSubclass ms1 = new MaliciousSubclass("file.txt"); MaliciousSubclass ms2 = ms1.Cloneclone(); // createsCreates a copy String s = ms1.get(); // returnsReturns filename System.out.println(s); // filenameFilename is "file.txt" ms2.replace(); // replacesReplaces all characters with 'x' // bothBoth ms1.get() and ms2.get() will subsequently return filename = 'xxxxxxxx' ms1.printFilename(); // filenameFilename becomes 'xxxxxxxx' ms2.printFilename(); // filenameFilename becomes 'xxxxxxxx' } } |
The malicious class creates an instance ms1
and produces a second instance ms2
by cloning the first. It then obtains a new filename
by invoking the get()
method on the first instance. At this point, the shared
flag is set to true. Because the second instance ms2
does not have its shared flag set to true, it is possible to alter the first instance ms1
using the replace()
method. This approach obviates any security efforts and severely violates the class's invariants.
Compliant Solution (Final Class)
The easiest way to prevent malicious subclasses is to declare SensitiveClass
to be final.
Code Block | ||
---|---|---|
| ||
final class SensitiveClass {
// ...
}
|
Compliant Solution (Final clone()
)
Sensitive classes should not neither implement the Cloneable
interface . If the class extends nor provide a copy constructor. Sensitive classes that extend from a superclass that implements Cloneable
(and is consequently are cloneable ), it's as a result) must provide a clone()
method should throw that throws a CloneNotSupportedException
. This exception must be caught and handled by the client code. A sensitive class that does not implement Cloneable
must also follow this advice . 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 issuesbecause it inherits the clone()
method from Object
. The class can prevent subclasses from being made cloneable by defining a final
clone()
method that always fails.
Code Block | ||
---|---|---|
| ||
finalclass SensitiveClass { // ... public final SensitiveClass Clone()clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } } |
Risk Assessment
This class fails to prevent malicious subclasses but does protect the data in SensitiveClass
. Its methods are protected by being declared final. For more information on handling malicious subclasses, see OBJ04-J. Provide mutable classes with copy functionality to safely allow passing instances to untrusted code.
Risk Assessment
Failure to make sensitive classes noncopyable can permit violations of class invariants and provide malicious subclasses with the opportunity to exploit the code to create new instances of objects, even in the presence of the default security manager (in the absence of custom security checks).
Rule |
---|
Severity | Likelihood | Remediation Cost | Priority | Level |
---|
OBJ07-J |
Medium |
Probable |
Medium | P8 | L2 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[Mcgraw 98|AA. Java References#Mcgraw 98]\]
\[[Wheeler 03|AA. Java References#Wheeler 03]\] 10.6. Java
\[[MITRE 09|AA. Java References#MITRE 09]\] [CWE ID 498|http://cwe.mitre.org/data/definitions/498.html] "Information Leak through Class Cloning", [CWE ID 491|http://cwe.mitre.org/data/definitions/491.html] "Public cloneable() Method Without Final (aka 'Object Hijack')" |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
CodeSonar |
| JAVA.CLASS.CLONE.CNC | clone Non-cloneable (Java) | ||||||
Parasoft Jtest |
| CERT.OBJ07.MCNC | Make your classes noncloneable |
Related Guidelines
CWE-498, Cloneable Class Containing Sensitive Information |
Bibliography
"Twelve Rules for Developing More Secure Java Code" | |
Section 10.6, "Java" |
...
MSC36-J. Understand how escape characters are interpreted when String literals are compiled 49. Miscellaneous (MSC) MSC38-J. Do not modify the underlying collection when an iteration is in progress