[tomcat7] 03/05: Fixed CVE-2016-6797: Unrestricted Access to Global Resources

Emmanuel Bourg ebourg-guest at moszumanska.debian.org
Sun Oct 30 21:03:54 UTC 2016


This is an automated email from the git hooks/post-receive script.

ebourg-guest pushed a commit to branch jessie
in repository tomcat7.

commit 0c45ade31c00fe81d0b8ac70e0da80bee40c60af
Author: Emmanuel Bourg <ebourg at apache.org>
Date:   Sun Oct 30 17:51:07 2016 +0100

    Fixed CVE-2016-6797: Unrestricted Access to Global Resources
---
 debian/changelog                   |   5 +
 debian/patches/CVE-2016-6797.patch | 244 +++++++++++++++++++++++++++++++++++++
 debian/patches/series              |   1 +
 3 files changed, 250 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 4e9c9a8..5fea2c1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -8,6 +8,11 @@ tomcat7 (7.0.56-3+deb8u5) jessie-security; urgency=high
     the SecurityManager. Tomcat's system property replacement feature for
     configuration files could be used by a malicious web application to bypass
     the SecurityManager and read system properties that should not be visible.
+  * Fixed CVE-2016-6797: The ResourceLinkFactory did not limit web application
+    access to global JNDI resources to those resources explicitly linked to the
+    web application. Therefore, it was possible for a web application to access
+    any global JNDI resource whether an explicit ResourceLink had been
+    configured or not.
   * CVE-2016-1240 follow-up:
     - The previous init.d fix was vulnerable to a race condition that could
       be exploited to make any existing file writable by the tomcat user.
diff --git a/debian/patches/CVE-2016-6797.patch b/debian/patches/CVE-2016-6797.patch
new file mode 100644
index 0000000..c1a1b94
--- /dev/null
+++ b/debian/patches/CVE-2016-6797.patch
@@ -0,0 +1,244 @@
+Description: Fixes CVE-2016-6797: The ResourceLinkFactory did not limit web
+ application access to global JNDI resources to those resources explicitly
+ linked to the web application. Therefore, it was possible for a web
+ application to access any global JNDI resource whether an explicit
+ ResourceLink had been configured or not.
+Origin: backport, https://svn.apache.org/r1757275
+--- a/java/org/apache/catalina/core/NamingContextListener.java
++++ b/java/org/apache/catalina/core/NamingContextListener.java
+@@ -41,6 +41,7 @@
+ import org.apache.catalina.ContainerEvent;
+ import org.apache.catalina.ContainerListener;
+ import org.apache.catalina.Context;
++import org.apache.catalina.Engine;
+ import org.apache.catalina.Host;
+ import org.apache.catalina.Lifecycle;
+ import org.apache.catalina.LifecycleEvent;
+@@ -68,6 +69,7 @@
+ import org.apache.naming.ResourceRef;
+ import org.apache.naming.ServiceRef;
+ import org.apache.naming.TransactionRef;
++import org.apache.naming.factory.ResourceLinkFactory;
+ import org.apache.tomcat.util.modeler.Registry;
+ import org.apache.tomcat.util.res.StringManager;
+ 
+@@ -344,6 +346,11 @@
+                         registry.unregisterComponent(objectName);
+                     }
+                 }
++
++                javax.naming.Context global = getGlobalNamingContext();
++                if (global != null) {
++                    ResourceLinkFactory.deregisterGlobalResourceAccess(global);
++                }
+             } finally {
+                 objectNames.clear();
+ 
+@@ -1167,6 +1174,17 @@
+             logger.error(sm.getString("naming.bindFailed", e));
+         }
+ 
++        ResourceLinkFactory.registerGlobalResourceAccess(
++                getGlobalNamingContext(), resourceLink.getName(), resourceLink.getGlobal());
++    }
++
++
++    private javax.naming.Context getGlobalNamingContext() {
++        if (container instanceof Context) {
++            Engine e = (Engine) ((Context) container).getParent().getParent();
++            return e.getService().getServer().getGlobalNamingContext();
++        }
++        return null;
+     }
+ 
+ 
+@@ -1270,6 +1288,7 @@
+             logger.error(sm.getString("naming.unbindFailed", e));
+         }
+ 
++        ResourceLinkFactory.deregisterGlobalResourceAccess(getGlobalNamingContext(), name);
+     }
+ 
+ 
+--- a/java/org/apache/naming/factory/ResourceLinkFactory.java
++++ b/java/org/apache/naming/factory/ResourceLinkFactory.java
+@@ -18,7 +18,10 @@
+ 
+ package org.apache.naming.factory;
+ 
++import java.util.HashMap;
+ import java.util.Hashtable;
++import java.util.Map;
++import java.util.concurrent.ConcurrentHashMap;
+ 
+ import javax.naming.Context;
+ import javax.naming.Name;
+@@ -50,6 +53,8 @@
+      */
+     private static Context globalContext = null;
+ 
++    private static Map<ClassLoader,Map<String,String>> globalResourceRegistrations =
++            new ConcurrentHashMap<ClassLoader,Map<String,String>>();
+ 
+     // --------------------------------------------------------- Public Methods
+ 
+@@ -69,6 +74,56 @@
+     }
+ 
+ 
++    public static void registerGlobalResourceAccess(Context globalContext, String localName,
++            String globalName) {
++        validateGlobalContext(globalContext);
++        ClassLoader cl = Thread.currentThread().getContextClassLoader();
++        Map<String,String> registrations = globalResourceRegistrations.get(cl);
++        if (registrations == null) {
++            // Web application initialization is single threaded so this is
++            // safe.
++            registrations = new HashMap<String,String>();
++            globalResourceRegistrations.put(cl, registrations);
++        }
++        registrations.put(localName, globalName);
++    }
++
++
++    public static void deregisterGlobalResourceAccess(Context globalContext, String localName) {
++        validateGlobalContext(globalContext);
++        ClassLoader cl = Thread.currentThread().getContextClassLoader();
++        Map<String,String> registrations = globalResourceRegistrations.get(cl);
++        if (registrations != null) {
++            registrations.remove(localName);
++        }
++    }
++
++
++    public static void deregisterGlobalResourceAccess(Context globalContext) {
++        validateGlobalContext(globalContext);
++        ClassLoader cl = Thread.currentThread().getContextClassLoader();
++        globalResourceRegistrations.remove(cl);
++    }
++
++
++    private static void validateGlobalContext(Context globalContext) {
++        if (ResourceLinkFactory.globalContext != null &&
++                ResourceLinkFactory.globalContext != globalContext) {
++            throw new SecurityException("Caller provided invalid global context");
++        }
++    }
++
++
++    private static boolean validateGlobalResourceAccess(String globalName) {
++        ClassLoader cl = Thread.currentThread().getContextClassLoader();
++        Map<String,String> registrations = globalResourceRegistrations.get(cl);
++        if (registrations != null && registrations.containsValue(globalName)) {
++            return true;
++        }
++        return false;
++    }
++
++
+     // -------------------------------------------------- ObjectFactory Methods
+ 
+ 
+@@ -93,6 +148,12 @@
+         RefAddr refAddr = ref.get(ResourceLinkRef.GLOBALNAME);
+         if (refAddr != null) {
+             globalName = refAddr.getContent().toString();
++            // When running under a security manager confirm that the current
++            // web application has really been configured to access the specified
++            // global resource
++            if (!validateGlobalResourceAccess(globalName)) {
++                return null;
++            }
+             Object result = null;
+             result = globalContext.lookup(globalName);
+             // FIXME: Check type
+--- /dev/null
++++ b/test/org/apache/naming/TestNamingContext.java
+@@ -0,0 +1,87 @@
++package org.apache.naming;
++
++import javax.naming.Context;
++import javax.naming.NamingException;
++
++import org.apache.catalina.deploy.ContextEnvironment;
++import org.apache.catalina.deploy.ContextResourceLink;
++import org.apache.catalina.startup.Tomcat;
++import org.apache.catalina.startup.TomcatBaseTest;
++import org.apache.naming.factory.ResourceLinkFactory;
++import org.junit.Assert;
++import org.junit.Test;
++
++public class TestNamingContext extends TomcatBaseTest {
++
++    private static final String COMP_ENV = "comp/env";
++    private static final String GLOBAL_NAME = "global";
++    private static final String LOCAL_NAME = "local";
++    private static final String DATA = "Cabbage";
++
++
++    @Test
++    public void testGlobalNaming() throws Exception {
++        Tomcat tomcat = getTomcatInstance();
++        tomcat.enableNaming();
++
++        org.apache.catalina.Context ctx = tomcat.addContext("", null);
++
++        tomcat.start();
++
++        Context webappInitial = ContextBindings.getContext(ctx);
++
++        // Nothing added at the moment so should be null
++        Object obj = doLookup(webappInitial, COMP_ENV + "/" + LOCAL_NAME);
++        Assert.assertNull(obj);
++
++        ContextEnvironment ce = new ContextEnvironment();
++        ce.setName(GLOBAL_NAME);
++        ce.setValue(DATA);
++        ce.setType(DATA.getClass().getName());
++
++        tomcat.getServer().getGlobalNamingResources().addEnvironment(ce);
++
++        // No link so still should be null
++        obj = doLookup(webappInitial, COMP_ENV + "/" + LOCAL_NAME);
++        Assert.assertNull(obj);
++
++        // Now add a resource link to the context
++        ContextResourceLink crl = new ContextResourceLink();
++        crl.setGlobal(GLOBAL_NAME);
++        crl.setName(LOCAL_NAME);
++        crl.setType(DATA.getClass().getName());
++        ctx.getNamingResources().addResourceLink(crl);
++
++        // Link exists so should be OK now
++        obj = doLookup(webappInitial, COMP_ENV + "/" + LOCAL_NAME);
++        Assert.assertEquals(DATA, obj);
++
++        // Try shortcut
++        ResourceLinkFactory factory = new ResourceLinkFactory();
++        ResourceLinkRef rlr = new ResourceLinkRef(DATA.getClass().getName(), GLOBAL_NAME, null, null);
++        obj = factory.getObjectInstance(rlr, null, null, null);
++        Assert.assertEquals(DATA, obj);
++
++        // Remove the link
++        ctx.getNamingResources().removeResourceLink(LOCAL_NAME);
++
++        // No link so should be null
++        obj = doLookup(webappInitial, COMP_ENV + "/" + LOCAL_NAME);
++        Assert.assertNull(obj);
++
++        // Shortcut should fail too
++        obj = factory.getObjectInstance(rlr, null, null, null);
++        Assert.assertNull(obj);
++    }
++
++
++    private Object doLookup(Context context, String name) {
++        Object result = null;
++        try {
++            result = context.lookup(name);
++        } catch (NamingException nnfe) {
++            // Ignore
++        }
++        return result;
++    }
++}
diff --git a/debian/patches/series b/debian/patches/series
index 1ad4cc7..296cb13 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -29,3 +29,4 @@ CVE-2016-0763.patch
 CVE-2016-3092.patch
 CVE-2016-5018.patch
 CVE-2016-6794.patch
+CVE-2016-6797.patch

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/tomcat7.git



More information about the pkg-java-commits mailing list