Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
bgColor#ccccff
langjava
// ...
    if (className == null) {
        throw new RuntimeOperationsException(new
            IllegalArgumentException("The class name cannot be null"),
                          "Exception occurred during object instantiation");
    }
    ReflectUtil.checkPackageAccess(className);
    try {
        if (loader == null)
// ...

Noncompliant Code Example (CERT Vul# 636312)

CERT Vulnerability 636312 describes a vulnerability in Java that was successfully exploited in August 2012. (The exploit actually used two vulnerabilities; the other one is described in SEC05-J. Do not use reflection to increase accessibility of classes, methods, or fields).

The goal of the exploit code was to access the private sun.awt.SunToolkit class. However, as the attack code runs in an applet, accessing it directly, using class.forName() would cause a SecurityException to be thrown. Consequently, the exploit code contains the following method to get a class, bypassing its security manager:

Code Block
bgColor#ffcccc
langjava
private Class GetClass(String paramString)
    throws Throwable
{
    Object arrayOfObject[] = new Object[1];
    arrayOfObject[0] = paramString;
    Expression localExpression = new Expression(Class.class, "forName", arrayOfObject);
    localExpression.execute();
    return (Class)localExpression.getValue();
}

The {[java.beans.Expression.execute()}} method delegates its work to the following method:

Code Block
bgColor#ffcccc
langjava
private Object invokeInternal() throws Exception {
  Object target = getTarget();
  String methodName = getMethodName();

  if (target == null || methodName == null) {
    throw new NullPointerException((target == null ? "target" :
                                   "methodName") + " should not be null");
  }

  Object[] arguments = getArguments();
  if (arguments == null) {
    arguments = emptyArray;
  }
  // Class.forName() won't load classes outside
  // of core from a class inside core. Special
  // case this method.
  if (target == Class.class && methodName.equals("forName")) {
    return ClassFinder.resolveClass((String)arguments[0], this.loader);
  }

// ...

The com.sun.beans.finder.ClassFinder.resolveClass() method delegates its work to the findClass() method:

Code Block
bgColor#ffcccc
langjava
public static Class<?> findClass(String name) throws ClassNotFoundException {
  try {
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    if (loader == null) {
      loader = ClassLoader.getSystemClassLoader();
    }
    if (loader != null) {
      return Class.forName(name, false, loader);
    }
  } catch (ClassNotFoundException exception) {
    // use current class loader instead
  } catch (SecurityException exception) {
    // use current class loader instead
  }
  return Class.forName(name);
}

While this method is called in the context of an applet, it uses Class.forName() to obtain the requested class. And Class.forName() only validates that the calling class is allowed to access the class. In this case the calling class (com.sun.beans.finder.ClassFinder) is indeed allowed, even though it acts on behalf of the malicious GetClass method.

Compliant Solution (CVE-2012-4681)

Oracle mitigated this vulnerability by patching the com.sun.beans.finder.ClassFinder.findClass() method. The checkPackageAccess() method checks the entire call stack to ensure that Class.forName() in this instance only fetches classes for trusted methods.

Code Block
bgColor#ccccff
langjava
public static Class<?> findClass(String name) throws ClassNotFoundException {
  checkPackageAccess(name);
  try {
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    if (loader == null) {
      // can be null in IE (see 6204697)
      loader = ClassLoader.getSystemClassLoader();
    }
    if (loader != null) {
      return Class.forName(name, false, loader);
    }

  } catch (ClassNotFoundException exception) {
    // use current class loader instead
  } catch (SecurityException exception) {
    // use current class loader instead
  }
  return Class.forName(name);
}

Noncompliant Code Example

In this noncompliant code example a call to System.loadLibrary() is embedded in a doPrivileged block. This is insecure because a library can be loaded on behalf of untrusted code. In essence, the untrusted code's class loader may be able to indirectly load a library even though it lacks sufficient permissions to do so directly. After loading the library, untrusted code can call native methods from the library if those methods are accessible. This is possible because the doPrivileged block stops security manager checks being applied to callers further up the execution chain.

...

Oracle Security Alert for CVE-2013-0422
Manion, Art, Anatomy of Java Exploits, CERT/CC Blog, January 15, 2013 2:00 PM

Guillardoy, Esteban (Immunity Products), Java 0-day analysis (CVE-2012-4681), August 28, 2012

...