In a JVM, a class is identified by its fully qualified class name and its Classloader. A class with the same name but a different package name is different, and a class with the same fully qualified name but which has been loaded with a different Classloader is also different. "Two classes are the same class (and consequently the same type) if they are loaded by the same class loader and they have the same fully qualified name" \[[JVMSpec 99|AA. Java References#JVMSpec 99]\] [§2.8.1 Class Names|http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html].Java Virtual Machine (JVM), "Two classes are the same class (and consequently the same type) if they are loaded by the same class loader and they have the same fully qualified name" [JVMSpec 1999]. Two classes with the same name but different package names are distinct, as are two classes with the same fully qualified name loaded by different class loaders. Wiki Markup
It could be necessary to check One may frequently want to know whether a given object has a specific class type or whether two objects have the same class type associated with them, for example, in when implementing the equals()
method. If the comparison is performed incorrectly, your the code might could assume that the two objects are of the same class when they 're notare not. As a result, class names must not be compared.
Depending on the function that this the insecure code performs, this might introduce a vulnerability it could be vulnerable to a mix-and-match attack. An attacker can supply code that is could supply a malicious class with the same fully qualified name as your class; if you rely on comparing the classname as a string, you might end up believing it is privileged code and granting it undue privilegesthe target class. If access to a protected resource is granted based on the comparison of class names alone, the unprivileged class could gain unwarranted access to the resource.
Conversely, the assumption that two classes deriving from the same codebase will result in are the same class in a JVM is error - prone. While it is usually true for common user Although this assumption is commonly observed to be true in desktop applications, it is typically not the case with J2EE servers like servlet containers, which could . The containers can use different class loader instances of Classloaders to be able to deploy and recall applications at runtime without restarting having to restart the JVM. In such situations, two objects whose classes come from the same codebase could be different classes appear to the JVM , and it could be confusing to get false from to be two different classes. Also note that the equals()
method on their respective classesmight not return true when comparing objects originating from the same codebase.
Noncompliant Code Example
In this This noncompliant code example , the code compares the name of the class of object h
auth
to the string "com.application.auth.DefaultAuthenticationHandler
and proceeds according to whether this comparison succeeds or not."
and branches on the result of the comparison:
Code Block | ||
---|---|---|
| ||
// determineDetermine whether object hauth has required/expected class nameobject if (hauth.getClass().getName().equals( "com.example.application.auth.DefaultAuthenticationHandler")) { // code assumes it's an authorized class... } |
The problem with this example is that another class could exist with the same name in the same Comparing fully qualified class names is insufficient because distinct class loaders can load differing classes with identical fully qualified names into a single JVM.
Compliant Solution
This compliant solution compares the class object of h
itself to object auth
to the class object of the class that the current class loader would load with the required name.for the canonical default authentication handler:
Code Block | ||
---|---|---|
| ||
// determineDetermine whether object hauth has required/expected class name if (hauth.getClass() == this.getClassLoader().loadClass("com.example.application.auth.DefaultAuthenticationHandler".class)) { // code determines authorized class loaded by same classloader// ... } |
The call to loadClass()
returns the class having the specified name in the current namespace (of the classloader), and right-hand side of the comparison directly names the class of the canonical authentication handler. In the event that the canonical authentication handler had not yet been loaded, the Java runtime manages the process of loading the class. Finally, the comparison is correctly performed on the two class objects.
Noncompliant Code Example
This noncompliant code example compares the names of the two classes class objects of objects x
and y
and behaves accordingly using the equals()
method. Again, it is possible that x
and y
are distinct classes with the same name if they come from different class loaders.
Code Block | ||
---|---|---|
| ||
// determineDetermine whether objects x and y have the same class name if (x.getClass().getName().equals( y.getClass().getName() )) { // codeObjects assumeshave objects havethe same class } |
Compliant Solution
This compliant solution correctly compares the two objects' classes.:
Code Block | ||
---|---|---|
| ||
// determineDetermine whether objects x and y have the same class if (x.getClass() == y.getClass()) { // codeObjects determineshave whetherthe objects have same class } |
Wiki Markup |
---|
The class objects will only be equal when they have the same class as defined in \[[JVMSpec 99|AA. Java References#JVMSpec 99]\] and repeated above. |
Risk Assessment
Incorrectly comparing Comparing classes solely using their names could give an attacker's class undesirable privilegescan allow a malicious class to bypass security checks and gain access to protected resources.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|
OBJ09-J |
High |
Unlikely |
Low |
P9 | L2 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
Wiki Markup |
---|
\[[JVMSpec 99|AA. Java References#JVMSpec 99]\] [§2.8.1 Class Names|http://java.sun.com/docs/books/jvms/second_edition/html/Concepts.doc.html]
\[[Christudas 05|AA. Java References#Christudas 05]\]
\[[Mcgraw 98|AA. Java References#Mcgraw 98]\]
\[[Wheeler 03|AA. Java References#Wheeler 03]\] [Java|http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/java.html]
\[[MITRE 09|AA. Java References#MITRE 09]\] [CWE ID 486|http://cwe.mitre.org/data/definitions/486.html] "Comparison of Classes by Name" |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
The Checker Framework |
| Signature String Checker | Ensure that the string representation of a type is properly used for example in Class.forName (see Chapter 13) | ||||||
Parasoft Jtest |
| CERT.OBJ09.CMP | Do not compare Class objects by name | ||||||
PVS-Studio |
| V6054 | |||||||
SonarQube |
| S1872 | Classes should not be compared by name |
Related Guidelines
Bibliography
Internals of Java Class Loading | |
"Twelve Rules for Developing More Secure Java Code" | |
...
OBJ33-J. Limit the extensibility of classes and methods 07. Object Orientation (OBJ) OBJ35-J. Use checked collections against external code