[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[FD] Apache Struts2 Core Cross-Origin Protection Exemption Miskeyed to a Deployment-Wide Path



Description
Apache Struts2 Core version 7.4.0 and below's `FetchMetadataInterceptor`, 
`CoepInterceptor`, and `CoopInterceptor` each compare their `exemptedPaths` 
configuration -- a per-interceptor-reference, administrator-supplied set of 
paths intended to exempt specific actions from the corresponding cross-origin 
protection -- against `HttpServletRequest.getContextPath()`.  
`getContextPath()` is fixed for the entire deployed web application and is 
identical on every request regardless of which action or servlet path is being 
invoked, so it cannot distinguish one action from another.

Impact
An administrator who configures `exemptedPaths` expecting it to exempt a 
specific action or endpoint, instead is configuring a value that can never 
match the real, single, deployment-wide context path returned on genuine 
traffic, so the per-action exemption never takes effect and the intended 
protection remains enforced everywhere, including on the endpoint the 
administrator believed was exempted.  More importantly, if an administrator's 
configured exemption string happens to coincide with the application's actual 
context path -- such as if an administrator assumes that the parameter takes a 
path-like value and supplies the deployment's own root or an equally-named 
segment -- `exemptedPaths.contains(contextPath)` evaluates to `true` on every 
single request to the application and Fetch Metadata request filtering, the 
Cross-Origin Embedder Policy (COEP) header, and the Cross-Origin Opener Policy 
(COOP) header are all silently disabled for the entire deployment (well beyond 
the endpoint
  that the administrator intended to exempt), disabling the protections that 
such code is intended to provide across the entire application.

Examples
Sample Code
All three interceptors, each in `struts2-core`, apply the identical pattern -- 
a per-action `exemptedPaths` set compared against the deployment-wide 
`getContextPath()` rather than against anything that actually varies per action.

```java
    private final Set<String> exemptedPaths = new HashSet<>();
    private final ResourceIsolationPolicy resourceIsolationPolicy = new 
StrutsResourceIsolationPolicy();

    @Inject(required = false)
    public void setExemptedPaths(String paths) {
        
this.exemptedPaths.addAll(TextParseUtil.commaDelimitedStringToSet(paths));
    }

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        ActionContext context = invocation.getInvocationContext();
        HttpServletRequest request = context.getServletRequest();

        addVaryHeaders(invocation);

        String contextPath = request.getContextPath();
        // Apply exemptions: paths/endpoints meant to be served cross-origin
        if (exemptedPaths.contains(contextPath)) {
            return invocation.invoke();
        }
```
Code snippet from `struts2-core`'s 
core/src/main/java/org/apache/struts2/interceptor/FetchMetadataInterceptor.java,
 lines 55-73

```java
    @Override
    public void beforeResult(ActionInvocation invocation, String resultCode) {
        HttpServletRequest req = 
invocation.getInvocationContext().getServletRequest();
        final String path = req.getContextPath();

        if (exemptedPaths.contains(path)) {
```
Snippet from `struts2-core`'s 
core/src/main/java/org/apache/struts2/interceptor/CoepInterceptor.java, lines 
59-63

```java
    @Override
    public void beforeResult(ActionInvocation invocation, String resultCode) {
        HttpServletRequest request = 
invocation.getInvocationContext().getServletRequest();
        String path = request.getContextPath();

        if (isExempted(path)) {
```
Code from `struts2-core`'s 
core/src/main/java/org/apache/struts2/interceptor/CoopInterceptor.java, lines 
61-65
_______________________________________________
Sent through the Full Disclosure mailing list
https://nmap.org/mailman/listinfo/fulldisclosure
Web Archives & RSS: https://seclists.org/fulldisclosure/