...
The noncompliant code example shows the code associated with initialization of a new Digester
instance in the org.apache.catalina.startup.ContextConfig
class. "A Digester
processes an XML input stream by matching a series of element nesting patterns to execute Rules that have been added prior to the start of parsing" [Tomcat 2009]. The code to initialize the Digester
follows:
Code Block | ||
---|---|---|
| ||
protected static Digester webDigester = null;
if (webDigester == null) {
webDigester = createWebDigester();
}
|
The createWebDigester()
method is responsible for creating the Digester
. This method calls createWebXMLDigester()
, which invokes the method DigesterFactory.newDigester()
. This method creates the new digester instance and sets a boolean
flag useContextClassLoader
to true
.
Code Block | ||
---|---|---|
| ||
// This method exists in the class DigesterFactory and is called by
// ContextConfig.createWebXmlDigester().
// which is in turn called by ContextConfig.createWebDigester()
// webDigester finally contains the value of digester defined
// in this method.
public static Digester newDigester(boolean xmlValidation,
boolean xmlNamespaceAware,
RuleSet rule) {
Digester digester = new Digester();
// ...
digester.setUseContextClassLoader(true);
// ...
return digester;
}
|
The useContextClassLoader
flag is used by Digester
to decide which ClassLoader
to use when loading new classes. When true, it uses the WebappClassLoader
, which is untrusted because it loads whatever classes are requested by various web applications.
Code Block | ||
---|---|---|
| ||
public ClassLoader getClassLoader() {
// ...
if (this.useContextClassLoader) {
// Uses the context class loader which was previously set
// to the WebappClassLoader
ClassLoader classLoader =
Thread.currentThread().getContextClassLoader();
}
return classloader;
}
|
The Digester.getParser()
method is subsequently called by Tomcat to process web.xml
and other files:
Code Block | ||
---|---|---|
| ||
// Digester.getParser() calls this method. It is defined in class Digester
public SAXParserFactory getFactory() {
if (factory == null) {
factory = SAXParserFactory.newInstance(); // Uses WebappClassLoader
// ...
}
return (factory);
}
|
...
The webDigester
is also declared final. This prevents any subclasses from assigning a new object reference to webDigester
. (See rule OBJ10-J. Do not use public static nonfinal variables for more information.) It also prevents a race condition where another thread could access webDigester
before it is fully initialized. (See rule OBJ11-J. Be wary of letting constructors throw exceptions for more information.)
Code Block | ||
---|---|---|
| ||
protected static final Digester webDigester = init();
protected Digester init() {
Digester digester = createWebDigester();
// Does not use the context Classloader at initialization
digester.getParser();
return digester;
}
|
...
Secure Coding Guidelines for the Java Programming Language, Version 3.0 | Guideline 6-3. Safely invoke standard APIs that bypass |
Android Implementation Details
On Android, the use of DexClassLoader
or PathClassLoader
requires caution.
Bibliography
[CVE 2011] | |
Section 4.3.2, Class Loader Delegation Hierarchy | |
[JLS 2005] | §4.3.2, The Class |
Bug ID 29936, API Class |