Gouri Sankar A created WW-5758:
----------------------------------

             Summary: Enforce @StrutsParameter authorization in 
AliasInterceptor's raw-parameter fallback
                 Key: WW-5758
                 URL: https://issues.apache.org/jira/browse/WW-5758
             Project: Struts 2
          Issue Type: Bug
          Components: Core
    Affects Versions: 7.3.0, 7.0.0, 7.4.0
            Reporter: Gouri Sankar A


AliasInterceptor copies a value from one named source to a developer-chosen 
target property, falling
back to the raw HTTP request parameter of the source name when the source does 
not resolve on the stack
(its own documented behavior, shown in its own javadoc example). That fallback 
value was never checked
against @StrutsParameter before being written to the target, unlike every other 
binding path in the
framework: ParametersInterceptor, ChainingInterceptor, CookieInterceptor, and 
the REST/JSON plugins (my
own earlier finding, WW-5642, already merged) all call into the shared 
ParameterAuthorizer before
binding. AliasInterceptor never did. alias is in defaultStack, so it runs on 
every request to any
default-configured action.

Tested on main at a235259 (7.5.0-SNAPSHOT), embedded Tomcat 10.1.34, stock 
struts-default, an action with
one @StrutsParameter-annotated property and one not. Binding the unannotated 
property directly
(?secret=DIRECT_ATTEMPT) is correctly rejected, stays untouched. The same 
property, reached by
configuring aliases to map a raw HTTP parameter name onto it and sending that 
parameter instead
(?rawParam=PWNED_VIA_ALIAS), is not rejected and takes the attacker supplied 
value directly.

The fix is deliberately narrower than checking every alias target. 
AliasInterceptor has two different
value sources: a name that resolves directly on the stack, which names state an 
earlier, properly
authorized bind already produced such as an earlier action in a chain, and the 
raw HTTP parameter
fallback, which is the only path that carries never authorized external input. 
Checking every target
unconditionally would have also blocked the first, legitimate category. I built 
that broader version
first, live tested it, found it silently broke a same request stack to stack 
copy with no HTTP parameter
involved at all, and narrowed the check to apply only when the value came from 
the fallback, matching
exactly what ChainingInterceptor already exempts by default for the same 
underlying reason.

Affects 7.0.0 through 7.4.0, verified directly on all three released versions 
by reading the code at each
tag. requireAnnotations has been the default since the very first 7.0 release 
and AliasInterceptor has
never checked it. Does not affect 6.x: requireAnnotations is not set in 6.x's 
default.properties at all,
confirmed directly on 6.12.0, so there is no default on control for any 
interceptor to bypass on that
line.

This is the same bug class as WW-5642, already merged: a secondary binding path 
that does not enforce
@StrutsParameter the way ParametersInterceptor does.

I have a patch with a regression test ready and will open a PR referencing this 
ticket.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to