Moderate severityNVD Advisory· Published Sep 5, 2012· Updated Apr 29, 2026
CVE-2012-4387
CVE-2012-4387
Description
Apache Struts 2.0.0 through 2.3.4 allows remote attackers to cause a denial of service (CPU consumption) via a long parameter name, which is processed as an OGNL expression.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
org.apache.struts.xwork:xwork-coreMaven | >= 2.0.0, < 2.3.4.1 | 2.3.4.1 |
Affected products
36cpe:2.3:a:apache:struts:2.0.0:*:*:*:*:*:*:*+ 34 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.3:*:*:*:*:*:*:*
- cpe:2.3:a:apache:struts:2.3.4:*:*:*:*:*:*:*
Patches
22 files changed · +68 −6
xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java+35 −5 modified@@ -95,9 +95,11 @@ * <!-- START SNIPPET: parameters --> * <p/> * <ul> - * <p/> * <li>ordered - set to true if you want the top-down property setter behaviour</li> - * <p/> + * <li>acceptParamNames - a comma delimited list of regular expressions to describe a whitelist of accepted parameter names. + * Don't change the default unless you know what you are doing in terms of security implications</li> + * <li>excludeParams - a comma delimited list of regular expressions to describe a blacklist of not allowed parameter names</li> + * <li>paramNameMaxLength - the maximum length of parameter names; parameters with longer names will be ignored; the default is 100 characters</li> * </ul> * <p/> * <!-- END SNIPPET: parameters --> @@ -129,6 +131,10 @@ public class ParametersInterceptor extends MethodFilterInterceptor { private static final Logger LOG = LoggerFactory.getLogger(ParametersInterceptor.class); + protected static final int PARAM_NAME_MAX_LENGTH = 100; + + private int paramNameMaxLength = PARAM_NAME_MAX_LENGTH; + boolean ordered = false; Set<Pattern> excludeParams = Collections.emptySet(); Set<Pattern> acceptParams = Collections.emptySet(); @@ -150,7 +156,16 @@ public static void setDevMode(String mode) { devMode = "true".equals(mode); } - public void setAcceptParamNames(String commaDelim) { + /** + * Sets a comma-delimited list of regular expressions to match + * parameters that are allowed in the parameter map (aka whitelist). + * <p/> + * Don't change the default unless you know what you are doing in terms + * of security implications. + * + * @param commaDelim A comma-delimited list of regular expressions + */ + public void setAcceptParamNames(String commaDelim) { Collection<String> acceptPatterns = ArrayUtils.asCollection(commaDelim); if (acceptPatterns != null) { acceptParams = new HashSet<Pattern>(); @@ -160,6 +175,16 @@ public void setAcceptParamNames(String commaDelim) { } } + /** + * If the param name exceeds the configured maximum length it will not be + * accepted. + * + * @param paramNameMaxLength Maximum length of param names + */ + public void setParamNameMaxLength(int paramNameMaxLength) { + this.paramNameMaxLength = paramNameMaxLength; + } + static private int countOGNLCharacters(String s) { int count = 0; for (int i = s.length() - 1; i >= 0; i--) { @@ -350,10 +375,15 @@ protected String getParameterLogMap(Map<String, Object> parameters) { } protected boolean acceptableName(String name) { - return isAccepted(name) && !isExcluded(name); + return isWithinLengthLimit(name) && isAccepted(name) + && !isExcluded(name); } - protected boolean isAccepted(String paramName) { + protected boolean isWithinLengthLimit( String name ) { + return name.length() <= paramNameMaxLength; + } + + protected boolean isAccepted(String paramName) { if (!this.acceptParams.isEmpty()) { for (Pattern pattern : acceptParams) { Matcher matcher = pattern.matcher(paramName);
xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java+33 −1 modified@@ -201,7 +201,39 @@ public void testParametersWithSpacesInTheName() throws Exception { assertEquals(0, existingMap.size()); } - public void testExcludedTrickyParameters() throws Exception { + public void testLargeParameterNameWithDefaultLimit() throws Exception { + ParametersInterceptor parametersInterceptor = createParametersInterceptor(); + doTestParameterNameLengthRestriction(parametersInterceptor, ParametersInterceptor.PARAM_NAME_MAX_LENGTH); + } + + public void testLargeParameterNameWithCustomLimit() throws Exception { + ParametersInterceptor parametersInterceptor = createParametersInterceptor(); + int limit = 20; + parametersInterceptor.setParamNameMaxLength(limit); + doTestParameterNameLengthRestriction(parametersInterceptor, limit); + } + + private void doTestParameterNameLengthRestriction( ParametersInterceptor parametersInterceptor, + int paramNameMaxLength ) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < paramNameMaxLength + 1; i++) { + sb.append("x"); + } + + Map<String, Object> actual = new LinkedHashMap<String, Object>(); + parametersInterceptor.setValueStackFactory(createValueStackFactory(actual)); + ValueStack stack = createStubValueStack(actual); + + Map<String, Object> parameters = new HashMap<String, Object>(); + parameters.put(sb.toString(), ""); + parameters.put("huuhaa", ""); + + Action action = new SimpleAction(); + parametersInterceptor.setParameters(action, stack, parameters); + assertEquals(1, actual.size()); + } + + public void testExcludedTrickyParameters() throws Exception { Map<String, Object> params = new HashMap<String, Object>() { { put("blah", "This is blah");
2 files changed · +68 −6
xwork-core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java+35 −5 modified@@ -96,9 +96,11 @@ * <!-- START SNIPPET: parameters --> * <p/> * <ul> - * <p/> * <li>ordered - set to true if you want the top-down property setter behaviour</li> - * <p/> + * <li>acceptParamNames - a comma delimited list of regular expressions to describe a whitelist of accepted parameter names. + * Don't change the default unless you know what you are doing in terms of security implications</li> + * <li>excludeParams - a comma delimited list of regular expressions to describe a blacklist of not allowed parameter names</li> + * <li>paramNameMaxLength - the maximum length of parameter names; parameters with longer names will be ignored; the default is 100 characters</li> * </ul> * <p/> * <!-- END SNIPPET: parameters --> @@ -130,6 +132,10 @@ public class ParametersInterceptor extends MethodFilterInterceptor { private static final Logger LOG = LoggerFactory.getLogger(ParametersInterceptor.class); + protected static final int PARAM_NAME_MAX_LENGTH = 100; + + private int paramNameMaxLength = PARAM_NAME_MAX_LENGTH; + boolean ordered = false; Set<Pattern> excludeParams = Collections.emptySet(); Set<Pattern> acceptParams = Collections.emptySet(); @@ -151,7 +157,16 @@ public static void setDevMode(String mode) { devMode = "true".equals(mode); } - public void setAcceptParamNames(String commaDelim) { + /** + * Sets a comma-delimited list of regular expressions to match + * parameters that are allowed in the parameter map (aka whitelist). + * <p/> + * Don't change the default unless you know what you are doing in terms + * of security implications. + * + * @param commaDelim A comma-delimited list of regular expressions + */ + public void setAcceptParamNames(String commaDelim) { Collection<String> acceptPatterns = ArrayUtils.asCollection(commaDelim); if (acceptPatterns != null) { acceptParams = new HashSet<Pattern>(); @@ -161,6 +176,16 @@ public void setAcceptParamNames(String commaDelim) { } } + /** + * If the param name exceeds the configured maximum length it will not be + * accepted. + * + * @param paramNameMaxLength Maximum length of param names + */ + public void setParamNameMaxLength(int paramNameMaxLength) { + this.paramNameMaxLength = paramNameMaxLength; + } + static private int countOGNLCharacters(String s) { int count = 0; for (int i = s.length() - 1; i >= 0; i--) { @@ -351,10 +376,15 @@ protected String getParameterLogMap(Map<String, Object> parameters) { } protected boolean acceptableName(String name) { - return isAccepted(name) && !isExcluded(name); + return isWithinLengthLimit(name) && isAccepted(name) + && !isExcluded(name); } - protected boolean isAccepted(String paramName) { + protected boolean isWithinLengthLimit( String name ) { + return name.length() <= paramNameMaxLength; + } + + protected boolean isAccepted(String paramName) { if (!this.acceptParams.isEmpty()) { for (Pattern pattern : acceptParams) { Matcher matcher = pattern.matcher(paramName);
xwork-core/src/test/java/com/opensymphony/xwork2/interceptor/ParametersInterceptorTest.java+33 −1 modified@@ -201,7 +201,39 @@ public void testParametersWithSpacesInTheName() throws Exception { assertEquals(0, existingMap.size()); } - public void testExcludedTrickyParameters() throws Exception { + public void testLargeParameterNameWithDefaultLimit() throws Exception { + ParametersInterceptor parametersInterceptor = createParametersInterceptor(); + doTestParameterNameLengthRestriction(parametersInterceptor, ParametersInterceptor.PARAM_NAME_MAX_LENGTH); + } + + public void testLargeParameterNameWithCustomLimit() throws Exception { + ParametersInterceptor parametersInterceptor = createParametersInterceptor(); + int limit = 20; + parametersInterceptor.setParamNameMaxLength(limit); + doTestParameterNameLengthRestriction(parametersInterceptor, limit); + } + + private void doTestParameterNameLengthRestriction( ParametersInterceptor parametersInterceptor, + int paramNameMaxLength ) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < paramNameMaxLength + 1; i++) { + sb.append("x"); + } + + Map<String, Object> actual = new LinkedHashMap<String, Object>(); + parametersInterceptor.setValueStackFactory(createValueStackFactory(actual)); + ValueStack stack = createStubValueStack(actual); + + Map<String, Object> parameters = new HashMap<String, Object>(); + parameters.put(sb.toString(), ""); + parameters.put("huuhaa", ""); + + Action action = new SimpleAction(); + parametersInterceptor.setParameters(action, stack, parameters); + assertEquals(1, actual.size()); + } + + public void testExcludedTrickyParameters() throws Exception { Map<String, Object> params = new HashMap<String, Object>() { { put("blah", "This is blah");
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
11- struts.apache.org/2.x/docs/s2-011.htmlnvdPatchVendor AdvisoryWEB
- secunia.com/advisories/50420nvdVendor Advisory
- github.com/advisories/GHSA-hrgc-54mv-58gvghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2012-4387ghsaADVISORY
- www.openwall.com/lists/oss-security/2012/09/01/4nvdWEB
- www.openwall.com/lists/oss-security/2012/09/01/5nvdWEB
- exchange.xforce.ibmcloud.com/vulnerabilities/78183nvdWEB
- github.com/apache/struts/commit/80e03182d66d9e6ab18f9a9a9b3c42725a1c89e9ghsaWEB
- github.com/apache/struts/commit/87935af56a27235e9399308ee1fcfb74f8edcefaghsaWEB
- issues.apache.org/jira/browse/WW-3860nvdWEB
- www.securityfocus.com/bid/55346nvd
News mentions
0No linked articles in our index yet.