...
Code Block | ||||
---|---|---|---|---|
| ||||
// ... 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 | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
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
...