Lukasz Lenart created WW-5705:
---------------------------------
Summary: StringIndexOutOfBoundsException authorizing a parameter
name that begins with a nesting character
Key: WW-5705
URL: https://issues.apache.org/jira/browse/WW-5705
Project: Struts 2
Issue Type: Bug
Affects Versions: 7.2.1, 7.3.0
Reporter: Lukasz Lenart
Fix For: 7.4.0
{{StrutsParameterAuthorizer#isAuthorized}} derives the root property of a
parameter name by cutting at the first nesting character ({{.}}, {{[}} or
{{(}}), then lower-cases its first character:
{code:java}
int nestingIndex = indexOfAny(parameterName, NESTING\_CHARS\_STR);
String rootProperty = nestingIndex == -1 ? parameterName :
parameterName.substring(0, nestingIndex);
String normalisedRootProperty = Character.toLowerCase(rootProperty.charAt(0)) +
rootProperty.substring(1);
{code}
When the name _begins_ with a nesting character, {{nestingIndex}} is 0,
{{substring(0, 0)}} yields an empty string, and {{charAt(0)}} throws
{{StringIndexOutOfBoundsException}}. The exception escapes the interceptor.
h4. Reachability
* {{ParametersInterceptor}} is *not* affected: {{isAcceptableName()}} applies
{{ACCEPTED\_PATTERNS}}, which requires a leading {{\w+}}, before authorization.
* The JSON plugin *is*: {{JSONInterceptor}} authorizes at
{{isAcceptableNode()}}, whereas the accepted-pattern check runs later, in
{{isAcceptableLeafName()}}, and only for leaf keys.
* The REST plugin's {{ContentTypeInterceptor}} authorizes body-derived paths
with no accepted- or excluded-pattern check beforehand.
Reproduced with the container's own {{StrutsParameterAuthorizer}}, under the
shipped default {{struts.parameters.requireAnnotations=true}}, with a JSON body
of {{{}{".foo":"x"}{}}} - the exception escapes {{JSONInterceptor.intercept()}}.
h4. Affected versions
The expression dates from WW-5352 (6.4.0), but nothing reached it with such a
name until WW-5624 wired the JSON and REST body channels through the authorizer
in 7.2.0.
6.x is not affected: {{requireAnnotations}} has no default there, there is no
{{ParameterAuthorizer}} at all, and {{ParametersInterceptor}} - its only caller
- filters names through the accepted patterns first.
h4. Impact
A failed request. No authorization bypass, no amplification, nothing persists
beyond the single request. Triaged as an ordinary robustness bug rather than a
vulnerability.
h4. Fix
A name beginning with a nesting character names no root property, so
authorization rejects it before normalisation rather than computing one.
The change is already included in the WW-5698 pull request
https://github.com/apache/struts/pull/1872 (commit {{2f3ce9601}}), since that
PR routes ModelDriven parameters through the same expression. It can be split
into its own PR if the release notes should attribute it separately.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)