VYPR
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.

PackageAffected versionsPatched versions
org.apache.struts:struts2-coreMaven
< 2.3.202.3.20

Affected products

51
  • Apache/Struts50 versions
    cpe: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

1
1a668af7f1ff

Uses the same logic as in ParametersInterceptor to use st of patterns

https://github.com/apache/strutsLukasz LenartMay 1, 2014via ghsa
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

News mentions

0

No linked articles in our index yet.