It is possible to reflectively access fields and methods of another one object from a given objectanother. Language access checks are enforced by the JVM to ensure policy compliance, while doing so. For instance, although an object is not normally allowed to access private members or invoke methods of another class, the APIs belonging to the java.lang.reflect
package allow an object to do so contingent upon performing the mirrored language access language access checks.
The table below lists the APIs that should be used with care.
APIs that mirror language checks |
---|
|
|
|
|
|
|
|
|
Note that the language access checks do not apply to java.lang.reflect.Field.setAccessible/getAccessible
methods but to the remaining set*
and get*
field methods. The former APIs are protected by standard security manager checks.
Noncompliant Code Example
In this noncompliant code snippet, the package-private field i
of class C
can be accessed from class ReflectionExample
. Method makeAccessible
accepts fieldName
as an input parameter which can be supplied by untrusted code. This is dangerous because despite the untrusted code not having the same capabilities as that of the immediate caller (method makeAccessible
), it is allowed to carry out sensitive operations. In this case, the immediate caller has the capability of modifying package-private fields without triggering any language access checks. Hostile code should not be allowed to make such modifications by using it as an oracle.
Code Block | ||
---|---|---|
| ||
// Class 'ReflectionExample' and 'C' belong to the same package public class ReflectionExample { public static void makeAccessible(String fieldName) { C c = new C(); try { Field f = c.getClass().getDeclaredField(fieldName); System.out.println(f.getInt(c)); // prints 10 f.setInt(c, 1); // set to 1; bypasses language access checks System.out.println(f.getInt(c)); // now prints 1 } catch(NoSuchFieldException nsfa){} catch(IllegalAccessException iae) {} } } class C { int i = 10; // package-private } |
Note that the language access checks do not apply to java.lang.reflect.Field.setAccessible/getAccessible
methods but to other set*
and get*
field methods. The successful execution of the former APIs is protected by standard security manager checks.
Compliant Solution
Compliant Solution
Do not operate on Avoid invoking affected APIs on Class
, Constructor
, Field
or Method
instances passed in from untrusted code. Even when the instances are acquired safely, do not use tainted inputs provided by untrusted code. Likewise, do not return values to the an untrusted caller. The table below lists the APIs that should be used with care. If you must use Reflection, make sure that the immediate caller (method) is isolated from hostile code by declaring it final
, reducing it's scope to private
and making it non-static
. Also, make declare sensitive fields in other classes (Class c
) as private
.
Code Block | ||
---|---|---|
| ||
private final void makeAccessible() { // private final String fieldName = "i"; // hardcode C c = new C(); // ... } class C { private int i = 10; // private } |
The permission ReflectPermission
with action suppressAccessChecks
should also not be granted so that the security manager blocks attempts to access private fields of other classes. (See SEC32-J. Do not grant ReflectPermission with action suppressAccessChecks)
...
APIs that mirror language checks
Noncompliant Code Example
This noncompliant code example accepts an instance of java.lang.Class
...
java.lang.reflect.Constructor.newInstance
...
java.lang.reflect.Field.get*
...
java.lang.reflect.Field.set*
...
java.lang.reflect.Method.invoke
...
java.util.concurrent.atomic.AtomicIntegerFieldUpdater.newUpdater
...
java.util.concurrent.atomic.AtomicLongFieldUpdater.newUpdater
...
java.util.concurrent.atomic.AtomicReferenceFieldUpdater.newUpdater
from untrusted code. No language access checks are carried out against this instance but instead, with the immediate caller of getInstance()
. This allows an attacker to let trusted code interleave with malicious code.
Code Block | ||
---|---|---|
| ||
public static void makeAccessible(Class c, String fieldName) {
try {
// ...
System.out.println(f.getInt(c)); // unsafe!
}
// ...
}
|
Compliant Solution
Avoid invoking affected APIs on Class
, Constructor
, Field
or Method
instances obtained from untrusted code. This can be done by explicitly instantiating the class within the makeAccessible
method.
Code Block | ||
---|---|---|
| ||
public static void makeAccessible() {
Class c = new C();
String fieldName = "i";
try {
// ...
System.out.println(f.getInt(c)); // unsafe!
}
// ...
}
|
Risk Assessment
Misuse of APIs that perform language
Risk Assessment
Performing access checks against the immediate caller , instead of against each caller in the execution sequence, may seriously compromise the security of a java applicationonly, can break data encapsulation.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
SEC04-J | medium | probable | medium | P8 | L2 |
...