Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: please check my changes
Wiki Markup
            The reflection APIs permit an object to access the fields and methods of another object by name, rather than by reference. The JVM enforces policy compliance during such accesses by performing language access checks. For example, although an object is ordinarily not 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 language defined access checks. It is important to note, however, that these access checks consider only the language level visibility of the immediate caller. Consequently, unwary programmers can afford an opportunity for a privilege escalation attack by untrusted callers.

The following table lists the APIs that should be used with care \[[SCG 2009|AA. Bibliography#SCG 09]\].
||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()}}|

Because the {{java.lang.reflect.Field}} {{setAccessible}} and {{getAccessible}} methods are used to instruct the JVM to override the language access checks, they perform standard (and more restrictive) security manager checks and consequently lack the vulnerability discussed in this rule. Nevertheless, these methods should be used only with extreme caution. The remaining {{set*()}} and {{get*()}} field reflection methods perform only the language access checks, and consequently are vulnerable.

Use of reflection complicates security analysis, and can introduce substantial security vulnerabilities. Consequently, programmers should avoid the use of the reflection APIs when it is feasible to do so. When use of reflection is necessary, exercise extreme caution. 

In particular, reflection must not be used to provide access to classes, methods, and fields, unless these items are already accessible without use of reflection. For example, use of reflection to access or modify fields is not allowed, unless those fields are already accessible and modifiable by other means, such as through getter and setter methods.

This rule is similar to [MET04-J. Do not increase the accessibility of overridden or hidden methods], but it warns against using reflection, rather than inheritance, to subvert accessibility.

h2. Noncompliant Code Example

In this noncompliant code example, the private fields {{i}} and {{j}} can be modified using reflection using a {{Field}}. Furthermore, any class can modify these fields using reflection via the {{zeroField()}} method. However, only class {{FieldExample}} can modify these fields without the use of reflection. 

Allowing hostile code to pass arbitrary field names to the {{zeroField()}} method can:
* Leak information about field names, by throwing an exception for invalid or inaccessible field names. See rule [ERR01-J. Do not allow exceptions to expose sensitive information] for additional information. This example complies with that rule by catching the relevant exceptions at the end of the method.
* Access potentially sensitive data that is visible to {{zeroField()}} but is hidden from the attacking method. This privilege escalation attack can be difficult to find during code review because the specific field(s) being accessed are controlled by strings in the attacker's code rather than by locally visible source code.

{code:bgColor=#FFcccc}
class FieldExample {
  private int i = 3;

  private int j = 4;

  public String toString() {
    return "FieldExample: i=" + i + ", j=" + j;
  }

  public void zeroI() {
    this.i = 0;
  }

  public void zeroField(String fieldName) {
    try {
      Field f = this.getClass().getDeclaredField(fieldName);
      // Subsequent access to field f passes language access checks
      // because makeAccessible could have accessed the field via
      // ordinary field references
      f.setInt(this, 0);
      // log appropriately or throw sanitized exception; see EXC06-J
    } catch (NoSuchFieldException ex) {
      // report to handler
    } catch (IllegalAccessException ex) {
      // report to handler
    }
  }


  public static void main(String[] args) {
    FieldExample fe = new FieldExample();
    System.out.println(fe.toString());
    for (String arg : args) {
      fe.zeroField(arg);
      System.out.println(fe.toString());
    }
  }
}
{code}

h2. Compliant Solution (Private)

If you must use reflection, make sure that the immediate caller (method) is isolated from hostile code by declaring it private or final, as in this compliant solution.

{code:bgColor=#ccccff}
class FieldExample {
  // ...

  private void zeroField(String fieldName) {
    // ...
  }
}
{code}

Note that when language access checks are overridden through use of {{java.lang.reflect.Field.setAccessible}}, the immediate caller gains access even to the private fields of other classes. Consequently, never grant the permission {{ReflectPermission}} with action {{suppressAccessChecks}} so that the security manager will block attempts to access private fields of other classes. See rule [jg:void ENV04-J. Do not grant ReflectPermission with target suppressAccessChecks] for more information. 


h2. Compliant Solution (Non-reflection)

When a class must use reflection to provide access to fields, it must also provide the same access using a non-reflection interface. This compliant solution provides limited setter methods that grant all callers the ability to zero out its fields without using reflection. If these setter methods comply with all other rules or security policies, the use of reflection also complies with this rule.

{code:bgColor=#ccccff}
class FieldExample {
  // ...

  public void zeroI() {
    this.i = 0;
  }
  public void zeroJ() {
    this.i = 0;
  }
}
{code}


h2. Noncompliant Code Example

In this noncompliant code example, the programmer intends that code that exists outside the package should beis prevented from creating a new instance of an arbitrary class. Consequently, the {{Trusted}} class uses a package-private constructor.  However, because the API is {{public}}, an attacker can pass {{Trusted.class}} itself as a parameter to the {{create()}} method and so bypass the language access checks that prevent him code outside the package from invoking the package-private constructor. The {{create()}} method returns an unauthorized instance of the {{Trusted}} class.  

{code:bgColor=#FFcccc}
package Safe;
public class Trusted {
  Trusted() { } // package private constructor
  public static <T> T create(Class<T> c) throws InstantiationException, IllegalAccessException {
    return c.newInstance();
  }
}
{code}

{code:bgColor=#FFcccc}
package Attacker;
import Safe.Trusted;

public class Attack {
  public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    System.out.println(Trusted.create(Trusted.class)); // succeeds
  }
}
{code}

In the presence of a security manager {{s}}, the {{Class.newInstance()}} method throws a security exception when either

{quote}
* an invocation of {{s.checkMemberAccess(this, Member.PUBLIC)}} denies creation of new instances of this class
* or the caller's class loader is not the same as or an ancestor of the class loader for the current class and invocation of {{s.checkPackageAccess()}} denies access to the package of this class 
{quote}.

The {{checkMemberAccess}} method "allows access to {{PUBLIC}} members, as well as access to and classes that have the same class loader as the caller," which may be unsafe, as demonstrated in this noncompliant code example. The same class loader as the caller.  However, the class loader comparison in the second condition is often insufficient; for example all applets share the same class loader by convention, consequently allowing a malicious applet to pass the security check in this case. Mitigate this vulnerability by invoking the {{checkPackageAccess()}} method directly.

h2. Compliant Solution (Access Reduction)

This compliant solution reduces the access of the {{create()}} method to package-private. As a result, any caller that can create a {{Trusted}} class using reflection could also simply call the {{Trusted}} constructor instead.

{code:bgColor=#ccccff}
package Safe;
public class Trusted {
  Trusted() { } // package private constructor
  static <T> T create(Class<T> c) throws InstantiationException, IllegalAccessException {
    return c.newInstance();
  }
}
{code}

h2. Compliant Solution (Security Manager Check)

This compliant solution uses the {{getConstructors()}} method to check whether the class provided as an argument has public constructors. The security issue becomes mootirrelevant when {{public}} constructors are present, because such constructors are already accessible even to malicious code. When {{public}} constructors are absent, the {{create()}} method uses the security manager's {{checkPackageAccess()}} method to ensure that all callers in the execution chain have sufficient permissions to access classes and their respective members defined in package {{Safe}}.

{code:bgColor=#ccccff}
package Safe;
import java.beans.Beans;
import java.io.IOException;

public class Trusted  {
  Trusted() { }
  
  public static <T> T create(Class<T> c) throws InstantiationException, IllegalAccessException {
    
    if(c.getConstructors().length == 0) {  // No public constructors  	  
      SecurityManager sm = System.getSecurityManager();    
      if (sm != null) {
        // throws an exception when access is forbidden          
        sm.checkPackageAccess("Safe");          
      }
    } 
    return c.newInstance(); // Safe to return     
  }  
}
{code}

The drawback of this compliant solution is that the class must be granted reflection permissions in order to permit the call to {{getConstructors()}}. 

{mc}
// HIDDEN TEXT
// code outside the package
package Attacker;
import Safe.Trusted;

public class Attack {
  public static void main(String[] args) {
    Object o = Trusted.create(Trusted.class); 
  }
}
{mc}

h2. Compliant Solution ({{java.beans}} Package)

This compliant solution uses the {{java.beans.Beans}} API to check whether the Class object being received has any {{public}} constructors. 

{code:bgColor=#ccccff}
public class Trusted  {
  Trusted() { }
  
  public static <T> T create(Class<T> c) throws  IOException, ClassNotFoundException {
    
    // Executes without exception only if there are public constructors
    ClassLoader cl = new SafeClassLoader();
    Object b = Beans.instantiate(cl, c.getName());
    return c.cast(b);      
  }  
}
{code}

The {{Beans.instantiate()}} method succeeds only when the class being instantiated has a {{public}} constructor; otherwise, it throws an {{IllegalAccessException}}. The method uses a class loader argument along with the name of the class to instantiate. Unlike the previous compliant solution, this approach avoids the need for any reflection permissions.


h2. Risk Assessment

Misuse of APIs that perform language access checks against the immediate caller only can break data encapsulation, leak sensitive information, or permit privilege escalation attacks.

|| Rule || Severity || Likelihood || Remediation Cost || Priority || Level ||
| SEC05-J | high | probable | medium | {color:red}{*}P12{*}{color} | {color:red}{*}L1{*}{color} |

h2. Related Guidelines

| [Secure Coding Guidelines for the Java Programming Language, Version 3.0|http://www.oracle.com/technetwork/java/seccodeguide-139067.html] | Guideline 6-5 Be aware of standard APIs that perform Java language access checks against the immediate caller |

h2. Bibliography

| \[[Chan 1999|AA. Bibliography#Chan 99]\] | java.lang.reflect AccessibleObject |

----
[!The CERT Oracle Secure Coding Standard for Java^button_arrow_left.png!|SEC04-J. Do not load trusted classes after allowing untrusted code to load arbitrary classes]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[!The CERT Oracle Secure Coding Standard for Java^button_arrow_up.png!|14. Platform Security (SEC)]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[!The CERT Oracle Secure Coding Standard for Java^button_arrow_right.png!|SEC06-J. Do not base security checks on untrusted sources]