High severityNVD Advisory· Published May 8, 2014· Updated May 6, 2026
CVE-2014-0116
CVE-2014-0116
Description
CookieInterceptor in Apache Struts 2.x before 2.3.20, when a wildcard cookiesName value is used, does not properly restrict access to the getClass method, which allows remote attackers to "manipulate" the ClassLoader and modify session state via a crafted request. NOTE: this vulnerability exists because of an incomplete fix for CVE-2014-0113.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.apache.struts:struts2-coreMaven | < 2.3.20 | 2.3.20 |
Affected products
51cpe:2.3:a:apache:struts:2.0.0:*:*:*:*:*:*:*+ 49 more
- cpe:2.3:a:apache:struts:2.0.0:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.10:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.11:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.11.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.11.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.12:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.13:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.14:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.4:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.5:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.6:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.7:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.8:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.0.9:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.1.0:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.1.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.1.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.1.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.1.4:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.1.5:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.1.6:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.1.8:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.1.8.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.2.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.2.1.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.2.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.2.3.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.1.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.1.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.12:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.14:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.14.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.14.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.14.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.15:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.15.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.15.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.15.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.16:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.16.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.16.2:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.4:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.4.1:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.7:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.8:*:*:*:*:*:*:*
Patches
11a668af7f1ffUses the same logic as in ParametersInterceptor to use st of patterns
2 files changed · +82 −16
core/src/main/java/org/apache/struts2/interceptor/CookieInterceptor.java+29 −16 modified@@ -33,6 +33,7 @@ import javax.servlet.http.Cookie; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -175,7 +176,13 @@ public class CookieInterceptor extends AbstractInterceptor { // Allowed names of cookies private Pattern acceptedPattern = Pattern.compile(ACCEPTED_PATTERN, Pattern.CASE_INSENSITIVE); - private Pattern excludedPattern = Pattern.compile(ExcludedPatterns.CLASS_ACCESS_PATTERN, Pattern.CASE_INSENSITIVE); + private Set<Pattern> excludedPatterns = new HashSet<Pattern>(); + + public CookieInterceptor() { + for (String pattern : ExcludedPatterns.EXCLUDED_PATTERNS) { + excludedPatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); + } + } /** * Set the <code>cookiesName</code> which if matched will allow the cookie @@ -253,13 +260,16 @@ public String intercept(ActionInvocation invocation) throws Exception { * @return true|false */ protected boolean isAcceptableValue(String value) { - boolean matches = !excludedPattern.matcher(value).matches(); - if (!matches) { - if (LOG.isTraceEnabled()) { - LOG.trace("Cookie value [#0] matches excludedPattern [#1]", value, ExcludedPatterns.CLASS_ACCESS_PATTERN); + for (Pattern excludedPattern : excludedPatterns) { + boolean matches = !excludedPattern.matcher(value).matches(); + if (!matches) { + if (LOG.isTraceEnabled()) { + LOG.trace("Cookie value [#0] matches excludedPattern [#1]", value, excludedPattern.toString()); + } + return false; } } - return matches; + return true; } /** @@ -293,23 +303,26 @@ protected boolean isAccepted(String name) { } /** - * Checks if name of Cookie match {@link #excludedPattern} + * Checks if name of Cookie match {@link #excludedPatterns} * * @param name of Cookie * @return true|false */ protected boolean isExcluded(String name) { - boolean matches = excludedPattern.matcher(name).matches(); - if (matches) { - if (LOG.isTraceEnabled()) { - LOG.trace("Cookie [#0] matches excludedPattern [#1]", name, ExcludedPatterns.CLASS_ACCESS_PATTERN); - } - } else { - if (LOG.isTraceEnabled()) { - LOG.trace("Cookie [#0] doesn't match excludedPattern [#1]", name, ExcludedPatterns.CLASS_ACCESS_PATTERN); + for (Pattern excludedPattern : excludedPatterns) { + boolean matches = excludedPattern.matcher(name).matches(); + if (matches) { + if (LOG.isTraceEnabled()) { + LOG.trace("Cookie [#0] matches excludedPattern [#1]", name, excludedPattern.toString()); + } + return true; + } else { + if (LOG.isTraceEnabled()) { + LOG.trace("Cookie [#0] doesn't match excludedPattern [#1]", name, excludedPattern.toString()); + } } } - return matches; + return false; } /**
core/src/test/java/org/apache/struts2/interceptor/CookieInterceptorTest.java+53 −0 modified@@ -383,6 +383,59 @@ protected boolean isAcceptableValue(String value) { assertFalse(excludedValue.get(pollution6)); } + public void testCookiesWithStrutsInternalsAccess() throws Exception { + MockHttpServletRequest request = new MockHttpServletRequest(); + String sessionCookieName = "session.userId"; + String sessionCookieValue = "session.userId=1"; + String appCookieName = "application.userId"; + String appCookieValue = "application.userId=1"; + String reqCookieName = "request.userId"; + String reqCookieValue = "request.userId=1"; + + request.setCookies( + new Cookie(sessionCookieName, "1"), + new Cookie("1", sessionCookieValue), + new Cookie(appCookieName, "1"), + new Cookie("1", appCookieValue), + new Cookie(reqCookieName, "1"), + new Cookie("1", reqCookieValue) + ); + ServletActionContext.setRequest(request); + + final Map<String, Boolean> excludedName = new HashMap<String, Boolean>(); + final Map<String, Boolean> excludedValue = new HashMap<String, Boolean>(); + + CookieInterceptor interceptor = new CookieInterceptor() { + @Override + protected boolean isAcceptableName(String name) { + boolean accepted = super.isAcceptableName(name); + excludedName.put(name, accepted); + return accepted; + } + + @Override + protected boolean isAcceptableValue(String value) { + boolean accepted = super.isAcceptableValue(value); + excludedValue.put(value, accepted); + return accepted; + } + }; + interceptor.setCookiesName("*"); + + MockActionInvocation invocation = new MockActionInvocation(); + invocation.setAction(new MockActionWithCookieAware()); + + interceptor.intercept(invocation); + + assertFalse(excludedName.get(sessionCookieName)); + assertFalse(excludedName.get(appCookieName)); + assertFalse(excludedName.get(reqCookieName)); + + assertFalse(excludedValue.get(sessionCookieValue)); + assertFalse(excludedValue.get(appCookieValue)); + assertFalse(excludedValue.get(reqCookieValue)); + } + public static class MockActionWithCookieAware extends ActionSupport implements CookiesAware { private static final long serialVersionUID = -6202290616812813386L;
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-hmhq-382q-mp56ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2014-0116ghsaADVISORY
- struts.apache.org/release/2.3.x/docs/s2-022.htmlnvdWEB
- www.huawei.com/en/security/psirt/security-bulletins/security-advisories/hw-350733.htmnvdWEB
- github.com/apache/struts/commit/1a668af7f1ffccea4a3b46d8d8c1fe1c7331ff02ghsaWEB
- secunia.com/advisories/59816nvd
- www.oracle.com/technetwork/topics/security/cpuapr2015-2365600.htmlnvd
- www.securityfocus.com/bid/67218nvd
News mentions
0No linked articles in our index yet.