...
Some superclasses must permit extension by trusted subclasses while simultaneously preventing extension by untrusted code. Declaring such superclasses to be final is infeasible because it would prevent the required extension by trusted code. Such problems require careful design for inheritance.
Consider two classes belonging to different protection domains: one is malicious and extends the other, which is trusted. Consider an object of the malicious subclass with a fully qualified invocation of a method defined by the trusted superclass, not overridden by the malicious class. In this case, the trusted superclass's permissions are examined to execute the method, and, as a result, the malicious object gets the method invoked inside the protection domain of the trusted superclass \[ [Gong 2003|AA. References#Gong 03]\]. Wiki Markup
One commonly suggested solution is to place code at each point where the superclass can be instantiated to ensure that the instance being created has the same type as the superclass. When the type is found to be that of a subclass rather than the superclass's type, the checking code performs a security manager check to ensure that malicious classes cannot misuse the superclass. This approach is insecure because it allows a malicious class to add a finalizer and obtain a partially initialized instance of the superclass. This attack is detailed in rule OBJ11-J. Be wary of letting constructors throw exceptions.
...
Noncompliant Code Example (BigInteger
)
This noncompliant code example extends the {{ Wiki Markup java.math.BigInteger
}} class. This class is non-final and consequently extendable. This can be a problem when operating on an instance of {{BigInteger
}} that was obtained from an untrusted client. For example, a malicious client could construct a spurious mutable {{BigInteger
}} instance by overriding {{BigInteger
}}'s member functions \[ [Bloch 2008|AA. References#Bloch 08]\].
The following code example demonstrates such an attack.
...
Noncompliant Code Example (Security Manager)
This noncompliant code example installs a security manager check in the constructor of the {{ Wiki Markup BigInteger
}} class. The security manager denies access when it detects that a subclass without the requisite permissions is attempting to instantiate the superclass \[ [SCG 2009|AA. References#SCG 09]\]. It also compares class types, in compliance with rule [OBJ09-J. Compare classes and not class names]. Note that this check does not prevent malicious extensions of {{BigInteger
}}, it instead prevents the creation of {{BigInteger
}} objects from untrusted code, which also prevents creation of objects of malicious extensions of {{BigInteger
}}.
Code Block | ||
---|---|---|
| ||
public class BigInteger { public BigInteger(String str) { securityManagerCheck(); // ... } // Check the permission needed to subclass BigInteger // throws a security exception if not allowed private void securityManagerCheck() { // ... } } |
...
Compliant Solution (Class Sanitization)
...
The instances of nonfinal classes obtained from untrusted sources must be used with care because their methods might be overridden by malicious methods. This potential vulnerability can be mitigated by making defensive copies of the acquired instances prior to use. This compliant solution demonstrates this technique for a {{BigInteger}} argument \[ BigInteger
argument [Bloch 2008|AA. References#Bloch 08]\].
Code Block | ||
---|---|---|
| ||
public static BigInteger safeInstance(BigInteger val) { // create a defensive copy if it is not java.math.BigInteger if (val.getClass() != java.math.BigInteger.class) { return new BigInteger(val.toByteArray()); } return val; } |
...
This compliant solution invokes a security manager check as a side effect of computing the Boolean value passed to a private constructor (as seen in rule OBJ11-J. Be wary of letting constructors throw exceptions). The rules for order of evaluation require that the security manager check must execute before invocation of the private constructor. Consequently, the security manager check also executes before invocation of any superclass's constructor. Note that the security manager check is made without regard to whether the object under construction has the type of the parent class or the type of a subclass (whether trusted or not).unmigrated-wiki-markup
This solution prevents the finalizer attack; it applies to Java SE 6 and later versions, where throwing an exception before the {{java.lang.Object
}} constructor exits prevents execution of finalizers \[ [SCG 2009|AA. References#SCG 09]\].].
Code Block | ||
---|---|---|
| ||
public class BigInteger { public BigInteger(String str) { this(str, check()); } private BigInteger(String str, boolean dummy) { // regular construction goes here } private static boolean check() { securityManagerCheck(); return true; } } |
...
Secure Coding Guidelines for the Java Programming Language, Version 3.0 | Guideline 1-2. Limit the extensibility of classes and methods |
Bibliography
[API 2006] | Class BigInteger | |||||||
Item 1. Consider static factory methods instead of constructors | ||||||||
Chapter 6, Enforcing Security Policy | ||||||||
[Lai 2008] | Java Insecurity, Accounting for Subtleties That Can Compromise Code | |||||||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="13d24f08-cc9d-4d3a-b142-c77e61afb9f2"><ac:plain-text-body><![CDATA[ | [[API 2006 | AA. References#API 06]] | Class BigInteger | ]]></ac:plain-text-body></ac:structured-macro> | ||||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="d67fdb91-bddb-4409-9c9b-827209a00c8d"><ac:plain-text-body><![CDATA[ | [[Bloch 2008 | AA. References#Bloch 08]] | Item 1. Consider static factory methods instead of constructors | ]]></ac:plain-text-body></ac:structured-macro> | ||||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="712f5ace-183e-48a1-8841-c50580c3e973"><ac:plain-text-body><![CDATA[ | [[Gong 2003 | AA. References#Gong 03]] | Chapter 6, Enforcing Security Policy | ]]></ac:plain-text-body></ac:structured-macro> | ||||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="4f717561-dc92-416f-b497-22b9b55f2f72"><ac:plain-text-body><![CDATA[ | [[Lai 2008 | AA. References#Lai 08]] | Java Insecurity, Accounting for Subtleties That Can Compromise Code | ]]></ac:plain-text-body></ac:structured-macro> | ||||
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="9dbe723e-4dc1-4eff-94ff-8be135d01686"><ac:plain-text-body><![CDATA[ | [[McGraw 1999 | AA. References#McGraw 99]] | Chapter Seven, Rule 3. Make everything final, unless there's a good reason not to | ]]></ac:plain-text-body></ac:structured-macro> | <ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="c01a8fae-2557-407e-8b78-99dad13e6ff1"><ac:plain-text-body><![CDATA[ | [[Ware 2008 | AA. References#Ware 08]] | unless there's a good reason not to |
[Ware 2008] ]]></ac:plain-text-body></ac:structured-macro> |
...
04. Object Orientation (OBJ) 04. Object Orientation (OBJ) OBJ01-J. Declare data members as private and provide accessible wrapper methods