Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: changed NCCE and added discussion to CS

It is possible to reflectively access fields and methods of another object from a given object. 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 checks.

...

In this noncompliant code snippet, the package-private field i of class C can be accessed from class ReflectionExample. Method makeAccessible accepts fieldName as input 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
bgColor#FFcccc
import java.lang.reflect.Field;

// 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.isAccessiblegetInt(c));
	 // prints 10
      f.setAccessible(true);
	System.out.println(f.isAccessible());
	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 {
  private 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

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 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 is isolated from hostile code by declaring it final, reducing it's scope to private and making it non-static. Also, make sensitive fields in other classes 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

java.lang.Class.newInstance

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

...