Improper Neutralization of Directives in Dynamically Evaluated Code in Spring Framework
Research is free — Hunters explains how the bug works, the root-cause code pattern, how the fix addresses it, and how to test whether a target is affected, in chat. Investigate & write exploit is a paid run — the engine reads the advisory and fix commits, then builds and validates a working proof-of-concept exploit with reproduction steps.
Affected versions
Details
VMware SpringSource Spring Framework before 2.5.6.SEC03, 2.5.7.SR023, and 3.x before 3.0.6, when a container supports Expression Language (EL), evaluates EL expressions in tags twice, which allows remote attackers to obtain sensitive information via a (1) name attribute in a (a) spring:hasBindErrors tag; (2) path attribute in a (b) spring:bind or (c) spring:nestedpath tag; (3) arguments, (4) code, (5) text, (6) var, (7) scope, or (8) message attribute in a (d) spring:message or (e) spring:theme tag; or (9) var, (10) scope, or (11) value attribute in a (f) spring:transform tag, aka "Expression Language Injection."
The fix
Deprecated Spring's own JSP expression evaluation
spring-web/src/test/java/org/springframework/web/util/ExpressionEvaluationUtilsTests.java+33 −12
@@ -1,5 +1,5 @@/*-* Copyright 2002-2011 the original author or authors.+* Copyright 2002-2012 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -16,6 +16,7 @@package org.springframework.web.util;+import javax.servlet.ServletContext;import javax.servlet.jsp.JspException;import javax.servlet.jsp.PageContext;import javax.servlet.jsp.el.ELException;@@ -33,7 +34,7 @@import static org.junit.Assert.*;/**-* @author Aled Arendsen+* @author Alef Arendsen* @author Juergen Hoeller* @since 16.09.2003*/@@ -43,9 +44,9 @@ public class ExpressionEvaluationUtilsTests {public void testIsSpringJspExpressionSupportActive() {MockServletContext sc = new MockServletContext();PageContext pc = new MockPageContext(sc);-assertTrue(ExpressionEvaluationUtils.isSpringJspExpressionSupportActive(pc));-sc.addInitParameter("springJspExpressionSupport", "false");assertFalse(ExpressionEvaluationUtils.isSpringJspExpressionSupportActive(pc));+sc.addInitParameter("springJspExpressionSupport", "true");+assertTrue(ExpressionEvaluationUtils.isSpringJspExpressionSupportActive(pc));}@Test@@ -82,7 +83,9 @@ public void testIsExpressionLanguage() {@Testpublic void testEvaluate() throws Exception {-PageContext ctx = new MockPageContext();+MockServletContext sc = new MockServletContext();+sc.addInitParameter("springJspExpressionSupport", "true");+MockPageContext ctx = new MockPageContext(sc);ctx.setAttribute("bla", "blie");assertEquals("blie", ExpressionEvaluationUtils.evaluate("test", "${bla}", String.class, ctx));@@ -99,7 +102,9 @@ public void testEvaluate() throws Exception {@Testpublic void testEvaluateWithConcatenation() throws Exception {-PageContext ctx = new MockPageContext();+MockServletContext sc = new MockServletContext();+sc.addInitParameter("springJspExpressionSupport", "true");+MockPageContext ctx = new MockPageContext(sc);ctx.setAttribute("bla", "blie");String expr = "text${bla}text${bla}text";@@ -139,7 +144,9 @@ public void testEvaluateWithConcatenation() throws Exception {@Testpublic void testEvaluateString() throws Exception {-PageContext ctx = new MockPageContext();+MockServletContext sc = new MockServletContext();+sc.addInitParameter("springJspExpressionSupport", "true");+MockPageContext ctx = new MockPageContext(sc);ctx.setAttribute("bla", "blie");assertEquals("blie", ExpressionEvaluationUtils.evaluateString("test", "${bla}", ctx));@@ -148,7 +155,9 @@ public void testEvaluateString() throws Exception {@Testpublic void testEvaluateStringWithConcatenation() throws Exception {-PageContext ctx = new MockPageContext();+MockServletContext sc = new MockServletContext();+sc.addInitParameter("springJspExpressionSupport", "true");+MockPageContext ctx = new MockPageContext(sc);ctx.setAttribute("bla", "blie");String expr = "text${bla}text${bla}text";@@ -180,7 +189,9 @@ public void testEvaluateStringWithConcatenation() throws Exception {@Testpublic void testEvaluateInteger() throws Exception {-PageContext ctx = new MockPageContext();+MockServletContext sc = new MockServletContext();+sc.addInitParameter("springJspExpressionSupport", "true");+MockPageContext ctx = new MockPageContext(sc);ctx.setAttribute("bla", new Integer(1));assertEquals(1, ExpressionEvaluationUtils.evaluateInteger("test", "${bla}", ctx));@@ -189,7 +200,9 @@ public void testEvaluateInteger() throws Exception {@Testpublic void testEvaluateBoolean() throws Exception {-PageContext ctx = new MockPageContext();+MockServletContext sc = new MockServletContext();+sc.addInitParameter("springJspExpressionSupport", "true");+MockPageContext ctx = new MockPageContext(sc);ctx.setAttribute("bla", new Boolean(true));assertTrue(ExpressionEvaluationUtils.evaluateBoolean("test", "${bla}", ctx));@@ -198,7 +211,9 @@ public void testEvaluateBoolean() throws Exception {@Testpublic void testRepeatedEvaluate() throws Exception {-PageContext ctx = new CountingMockPageContext();+MockServletContext sc = new MockServletContext();+sc.addInitParameter("springJspExpressionSupport", "true");+PageContext ctx = new CountingMockPageContext(sc);CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator();ctx.setAttribute("bla", "blie");ctx.setAttribute("blo", "blue");@@ -218,7 +233,9 @@ public void testRepeatedEvaluate() throws Exception {@Testpublic void testEvaluateWithComplexConcatenation() throws Exception {-PageContext ctx = new CountingMockPageContext();+MockServletContext sc = new MockServletContext();+sc.addInitParameter("springJspExpressionSupport", "true");+PageContext ctx = new CountingMockPageContext(sc);CountingMockExpressionEvaluator eval = (CountingMockExpressionEvaluator) ctx.getExpressionEvaluator();ctx.setAttribute("bla", "blie");ctx.setAttribute("blo", "blue");@@ -247,6 +264,10 @@ public void testEvaluateWithComplexConcatenation() throws Exception {private static class CountingMockPageContext extends MockPageContext {+public CountingMockPageContext(ServletContext servletContext) {+super(servletContext);+}+private ExpressionEvaluator eval = new CountingMockExpressionEvaluator(this);public ExpressionEvaluator getExpressionEvaluator() {
Deprecated Spring's own JSP expression evaluation
spring-web/src/main/java/org/springframework/web/util/ExpressionEvaluationUtils.java+12 −13
@@ -1,5 +1,5 @@/*-* Copyright 2002-2011 the original author or authors.+* Copyright 2002-2012 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.@@ -39,7 +39,10 @@* @author Alef Arendsen* @since 11.07.2003* @see javax.servlet.jsp.el.ExpressionEvaluator#evaluate+* @deprecated as of Spring 3.2, in favor of the JSP 2.0+ native support+* for embedded expressions in JSP pages (also applying to tag attributes)*/+@Deprecatedpublic abstract class ExpressionEvaluationUtils {/**@@ -64,13 +67,9 @@ public abstract class ExpressionEvaluationUtils {* containers with web applications declaring Servlet 2.4 or higher in their* <code>web.xml</code>. For backwards compatibility, Spring's expression support* will remain active for applications declaring Servlet 2.3 or earlier. However,-* on Servlet 2.4/2.5 containers, we can't find out what the application has declared,-* so we'll also fall back to keeping expression support active in such a case.-* <p><b>Recommendations:</b> Explicitly set "springJspExpressionSupport" to "false"-* in order to prevent double evaluation for Servlet 2.4+ based applications.-* On Servlet 3.0 containers, this will be done for you by default by the framework.-* If for some reason you nevertheless want Spring's JSP expression support to be-* active, explicitly set the "springJspExpressionSupport" context-param to "true".+* on Servlet 2.4/2.5 containers, we can't find out what the application has declared;+* as of Spring 3.2, we won't activate Spring's expression support at all then since+* it got deprecated and will be removed in the next iteration of the framework.* @param pageContext current JSP PageContext* @return <code>true</code> if active (ExpressionEvaluationUtils will actually evaluate expressions);* <code>false</code> if not active (ExpressionEvaluationUtils will return given values as-is,@@ -84,13 +83,13 @@ public static boolean isSpringJspExpressionSupportActive(PageContext pageContext}if (sc.getMajorVersion() >= 3) {// We're on a Servlet 3.0+ container: Let's check what the application declares...-if (sc.getEffectiveMajorVersion() > 2 || sc.getEffectiveMinorVersion() > 3) {-// Application declares Servlet 2.4+ in its web.xml: JSP 2.0 expressions active.-// Skip our own expression support in order to prevent double evaluation.-return false;+if (sc.getEffectiveMajorVersion() == 2 && sc.getEffectiveMinorVersion() < 4) {+// Application declares Servlet 2.3- in its web.xml: JSP 2.0 expressions not active.+// Activate our own expression support.+return true;}}-return true;+return false;}/**
Deprecated Spring's own JSP expression evaluation
spring-webmvc/src/test/java/org/springframework/web/servlet/tags/AbstractTagTests.java+1 −0
@@ -41,6 +41,7 @@ public abstract class AbstractTagTests extends TestCase {protected MockPageContext createPageContext() {MockServletContext sc = new MockServletContext();+sc.addInitParameter("springJspExpressionSupport", "true");SimpleWebApplicationContext wac = new SimpleWebApplicationContext();wac.setServletContext(sc);wac.setNamespace("test");
References
- ADVISORYhttps://nvd.nist.gov/vuln/detail/CVE-2011-2730
- WEBhttps://github.com/spring-projects/spring-framework/commit/62ccc8dd7e645fb91705d44919abac838cb5ca3f
- WEBhttps://github.com/spring-projects/spring-framework/commit/9772eb8410e37cd0bdec0d1b133218446c778beb
- WEBhttps://github.com/spring-projects/spring-framework/commit/b8d86330d1fadc645630416c3aaebf131bf749fc
- WEBhttps://docs.google.com/document/d/1dc1xxO8UMFaGLOwgkykYdghGWm_2Gn0iCrxFsympqcE/edit
- PACKAGEhttps://github.com/spring-projects/spring-framework
- WEBhttp://bugs.debian.org/cgi-bin/bugreport.cgi?bug=677814
- WEBhttp://rhn.redhat.com/errata/RHSA-2013-0191.html
- WEBhttp://rhn.redhat.com/errata/RHSA-2013-0192.html
- WEBhttp://rhn.redhat.com/errata/RHSA-2013-0194.html
- WEBhttp://rhn.redhat.com/errata/RHSA-2013-0195.html
- WEBhttp://rhn.redhat.com/errata/RHSA-2013-0196.html