[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

tomcat6: CVE-2014-7810: Security Manager bypass by expression language



Source: tomcat6
Version: 6.0.41-2+squeeze6
Severity: normal
Tags: security patch upstream fixed-upstream

Dear Debian Java maintainers,

The Tomcat security team has identified a security issue [cve] that
allows malicious web applications to bypass the Security Manager, by the
use of expression language. The code related to this vulnerability is
present in squeeze and wheezy.

I have prepared the attached patches for squeeze, based on [fix].

[cve] https://security-tracker.debian.org/tracker/CVE-2014-7810
[fix] http://svn.apache.org/viewvc?view=revision&revision=1645366
      http://svn.apache.org/viewvc?view=revision&revision=1659538

If you fix the vulnerability please also make sure to include the
CVE (Common Vulnerabilities & Exposures) id in your changelog entry.

Please adjust the affected versions in the BTS as needed.

Cheers!

Santiago

P.S. This is part of my first security bug reports against tomcat.
Please let me know how can I improve them.
Description: Fix potential BeanELResolver issue when running under a security manager.
 Some classes may not be accessible but may have accessible interfaces.
 This is part of the fix for CVE-2014-7810
Origin: http://svn.apache.org/viewvc?view=revision&revision=1645366

--- a/java/javax/el/BeanELResolver.java
+++ b/java/javax/el/BeanELResolver.java
@@ -188,25 +188,49 @@
 		return null;
 	}
 
-	protected final static class BeanProperties {
-		private final Map<String, BeanProperty> properties;
+    protected final static class BeanProperties {
+        private final Map<String, BeanProperty> properties;
 
-		private final Class<?> type;
+        private final Class<?> type;
 
-		public BeanProperties(Class<?> type) throws ELException {
-			this.type = type;
-			this.properties = new HashMap<String, BeanProperty>();
-			try {
-				BeanInfo info = Introspector.getBeanInfo(this.type);
-				PropertyDescriptor[] pds = info.getPropertyDescriptors();
-				for (int i = 0; i < pds.length; i++) {
-					this.properties.put(pds[i].getName(), new BeanProperty(
-							type, pds[i]));
-				}
-			} catch (IntrospectionException ie) {
-				throw new ELException(ie);
-			}
-		}
+        public BeanProperties(Class<?> type) throws ELException {
+            this.type = type;
+            this.properties = new HashMap<String, BeanProperty>();
+            try {
+                BeanInfo info = Introspector.getBeanInfo(this.type);
+                PropertyDescriptor[] pds = info.getPropertyDescriptors();
+                for (PropertyDescriptor pd: pds) {
+                    this.properties.put(pd.getName(), new BeanProperty(type, pd));
+                }
+                if (System.getSecurityManager() != null) {
+                    // When running with SecurityManager, some classes may be
+                    // not accessible, but have accessible interfaces.
+                    populateFromInterfaces(type);
+                }
+            } catch (IntrospectionException ie) {
+                throw new ELException(ie);
+            }
+        }
+
+        private void populateFromInterfaces(Class<?> aClass) throws IntrospectionException {
+            Class<?> interfaces[] = aClass.getInterfaces();
+            if (interfaces.length > 0) {
+                for (Class<?> ifs : interfaces) {
+                    BeanInfo info = Introspector.getBeanInfo(ifs);
+                    PropertyDescriptor[] pds = info.getPropertyDescriptors();
+                    for (PropertyDescriptor pd : pds) {
+                        if (!this.properties.containsKey(pd.getName())) {
+                            this.properties.put(pd.getName(), new BeanProperty(
+                                    this.type, pd));
+                        }
+                    }
+                }
+            }
+            Class<?> superclass = aClass.getSuperclass();
+            if (superclass != null) {
+                populateFromInterfaces(superclass);
+            }
+        }
 
 		private BeanProperty get(ELContext ctx, String name) {
 			BeanProperty property = this.properties.get(name);
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -952,6 +952,15 @@
       </fix>
     </changelog>
   </subsection>
+  <subsection name="Jasper">
+    <changelog>
+      <fix>
+        Fix potential issue with BeanELResolver when running under a security
+        manager. Some classes may not be accessible but may have accessible
+        interfaces. (markt)
+      </fix>
+    </changelog>
+  </subsection>
   <subsection name="Web applications">
     <changelog>
       <fix>
Description: Backport some Jasper clean-up that might provide a marginal performance improvement.
 Even if it doesn't it removes some unnecessary code.
 This is part of the fix for CVE-2014-7810
Origin: http://svn.apache.org/viewvc?view=revision&revision=1659538

--- a/java/org/apache/jasper/runtime/PageContextImpl.java
+++ b/java/org/apache/jasper/runtime/PageContextImpl.java
@@ -5,9 +5,9 @@
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
- * 
+ *
  *      http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -59,7 +59,7 @@
 /**
  * Implementation of the PageContext class from the JSP spec. Also doubles as a
  * VariableResolver for the EL.
- * 
+ *
  * @author Anil K. Vijendran
  * @author Larry Cable
  * @author Hans Bergsten
@@ -70,7 +70,7 @@
  */
 public class PageContextImpl extends PageContext {
 
-    private static final JspFactory jspf = JspFactory.getDefaultFactory(); 
+    private static final JspFactory jspf = JspFactory.getDefaultFactory();
 
     private BodyContentImpl[] outs;
 
@@ -96,12 +96,12 @@
     private transient ServletResponse response;
 
     private transient HttpSession session;
-    
+
     private transient ELContextImpl elContext;
 
     private boolean isIncluded;
-    
-    
+
+
     // initial output stream
     private transient JspWriter out;
 
@@ -137,7 +137,7 @@
         this.errorPageURL = errorPageURL;
         this.request = request;
         this.response = response;
-        
+
         // initialize application context
         this.applicationContext = JspApplicationContextImpl.getInstance(context);
 
@@ -589,7 +589,7 @@
      * Returns the exception associated with this page context, if any. <p/>
      * Added wrapping for Throwables to avoid ClassCastException: see Bugzilla
      * 31171 for details.
-     * 
+     *
      * @return The Exception associated with this page context, if any.
      */
     public Exception getException() {
@@ -875,7 +875,7 @@
      * go away once the EL interpreter moves out of JSTL and into its own
      * project. For now, this is necessary because the standard machinery is too
      * slow.
-     * 
+     *
      * @param expression
      *            The expression to be evaluated
      * @param expectedType
@@ -887,39 +887,14 @@
      * @return The result of the evaluation
      */
     public static Object proprietaryEvaluate(final String expression,
-            final Class expectedType, final PageContext pageContext,
+            final Class<?> expectedType, final PageContext pageContext,
             final ProtectedFunctionMapper functionMap, final boolean escape)
             throws ELException {
-        Object retValue;
         final ExpressionFactory exprFactory = jspf.getJspApplicationContext(pageContext.getServletContext()).getExpressionFactory();
-        if (SecurityUtil.isPackageProtectionEnabled()) {
-            try {
-                retValue = AccessController
-                        .doPrivileged(new PrivilegedExceptionAction() {
-
-                            public Object run() throws Exception {
-                                ELContextImpl ctx = (ELContextImpl) pageContext.getELContext();
-                                ctx.setFunctionMapper(new FunctionMapperImpl(functionMap));
-                                ValueExpression ve = exprFactory.createValueExpression(ctx, expression, expectedType);
-                                return ve.getValue(ctx);
-                            }
-                        });
-            } catch (PrivilegedActionException ex) {
-                Exception realEx = ex.getException();
-                if (realEx instanceof ELException) {
-                    throw (ELException) realEx;
-                } else {
-                    throw new ELException(realEx);
-                }
-            }
-        } else {
-            ELContextImpl ctx = (ELContextImpl) pageContext.getELContext();
-            ctx.setFunctionMapper(new FunctionMapperImpl(functionMap));
-            ValueExpression ve = exprFactory.createValueExpression(ctx, expression, expectedType);
-            retValue = ve.getValue(ctx);
-        }
-
-        return retValue;
+        ELContextImpl ctx = (ELContextImpl) pageContext.getELContext();
+        ctx.setFunctionMapper(new FunctionMapperImpl(functionMap));
+        ValueExpression ve = exprFactory.createValueExpression(ctx, expression, expectedType);
+        return ve.getValue(ctx);
     }
 
     public ELContext getELContext() {
--- a/java/org/apache/jasper/security/SecurityClassLoad.java
+++ b/java/org/apache/jasper/security/SecurityClassLoad.java
@@ -93,8 +93,6 @@
                 "runtime.PageContextImpl$11");      
             loader.loadClass( basePackage +
                 "runtime.PageContextImpl$12");      
-            loader.loadClass( basePackage +
-                "runtime.PageContextImpl$13");      
 
             loader.loadClass( basePackage +
                 "runtime.JspContextWrapper");   

Attachment: signature.asc
Description: Digital signature


Reply to: