https://bz.apache.org/bugzilla/show_bug.cgi?id=70022

            Bug ID: 70022
           Summary: mod_proxy_fcgi: Null-byte injection via unchecked
                    return of ap_unescape_url_keep2f leads to PATH_INFO
                    truncation and security filter bypass
           Product: Apache httpd-2
           Version: 2.4.67
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: major
          Priority: P2
         Component: mod_proxy_fcgi
          Assignee: [email protected]
          Reporter: [email protected]
  Target Milestone: ---

Summary:
mod_proxy_fcgi: Null-byte injection via unchecked return of
ap_unescape_url_keep2f leads to PATH_INFO truncation and security filter bypass

Description:

Vulnerability Overview
A chain of three coding flaws in modules/proxy/mod_proxy_fcgi.c, server/util.c
and server/util_fcgi.c allows an unauthenticated remote attacker to inject a
literal null byte into the PATH_INFO environment variable sent to a FastCGI
backend, causing its value to be truncated. This can be exploited to bypass
<FilesMatch> and other security filters that rely on the uncorrupted path.

The vulnerability exists in all proxy-fcgi-pathinfo modes: unescape, first-dot,
and last dot. It affects Apache httpd 2.4.x up to and including the latest
2.4.6


Root Cause

 vuln 1 Unchecked Return Value (CWE-252)
In proxy_fcgi_canon() (mod_proxy_fcgi.c line ~180), the return value of
ap_unescape_url_keep2f() is ignored:

```c
r->path_info = apr_pstrcat(r->pool, "/", path, NULL);
if (!strcasecmp(pathinfo_type, "unescape")) {
    ap_unescape_url_keep2f(r->path_info, 0);   // return value ignored
}

```
ap_unescape_url_keep2f() returns HTTP_NOT_FOUND when it encounters a %00
sequence, but proxy_fcgi_canon() continues and returns OK.




vuln  2  

 Null Byte Written Despite Detection (CWE-158)
In server/util.c (unescape_url() function, around line 1906-1911), even after
detecting a null byte and setting badpath = 1, the function still writes the
byte into the output buffer:

if ((decoded == '\0') || ...) {
    badpath = 1;
    *x = decoded;   // null byte is still written!
    y += 2;
}


This corrupts the string even though the function intends to reject it.



vuln 3  strlen() Truncation in FCGI Encoder (CWE-170)

In server/util_fcgi.c (lines 156 and 229), ap_fcgi_encoded_env_len() and
ap_fcgi_encode_env() use strlen() to determine the length of environment
variable values:

vallen = elts[i].val ? strlen(elts[i].val) : 0;
...
memcpy(itr, elts[i].val, vallen);




Because PATH_INFO now contains a literal \0, strlen reports a truncated length,
and only the bytes before the null are sent to the backend.


---


Bypass of the 2.4.60 Null-Byte Hardening
Apache 2.4.60 added a check in the core URL decoder to reject %00. However,
this check only performs a single decoding pass. An attacker can use
double-encoding %2500:

Core decoder: %25 → %, leaving the literal text %00 in the URI. The core
null-byte check does not trigger.

mod_proxy_fcgi later decodes a second time, turning %00 into \0.

Thus the hardening is entirely circumvented.


Attack Scenario: FilesMatch Bypass
Administrator restricts an upload directory:

apache
<Directory "/var/www/html/uploads">
    <FilesMatch "\.php$">
        Require all denied
    </FilesMatch>
</Directory>




Attacker sends:
GET /uploads/shell.php%2500.png HTTP/1.1

Apache's core access control inspects the URI and sees a file ending in .png.
The <FilesMatch "\.php$"> rule does not match. The request is authorized.

mod_proxy_fcgi processes the request, calls ap_unescape_url_keep2f() which
injects a null byte into PATH_INFO and returns an error that is ignored.

The FastCGI encoder measures PATH_INFO with strlen(), finds the early \0, and
sends PATH_INFO = /uploads/shell.php to the backend.

A backend that uses PATH_INFO for file resolution will now see the malicious
script path instead of the safe .png that Apache authorized.




---



# impact
Unauthenticated security filter bypass  <FilesMatch>, mod_security rules, and
WAFs that inspect the uncorrupted URL are rendered blind.

Backend path confusion  Custom FastCGI applications (including C/C++
microservices) that rely on PATH_INFO for file inclusion or routing may be
tricked into accessing unintended resources, potentially leading to arbitrary
code execution.

Deterministic exploitation   No race condition, no memory corruption; one
single HTTP request is sufficient.


---


Affected Versions
All 2.4.x releases that include mod_proxy_fcgi (introduced in 2.4.7).

Confirmed on 2.4.66 and 2.4.66 (latest).

The double encoding bypass works against the 2.4.60 mitigation.




---


Proposed Patch

Check the return value of ap_unescape_url_keep2f() and abort the request if it
fails:


--- a/modules/proxy/mod_proxy_fcgi.c
+++ b/modules/proxy/mod_proxy_fcgi.c
@@ -176,8 +176,12 @@ static int proxy_fcgi_canon(request_rec *r, char *url)
              */
             r->path_info = apr_pstrcat(r->pool, "/", path, NULL);
             if (!strcasecmp(pathinfo_type, "unescape")) {
-                ap_unescape_url_keep2f(r->path_info, 0);
+                int rv = ap_unescape_url_keep2f(r->path_info, 0);
+                if (rv != OK) {
+                    return rv;
+                }
             }


Additionally, unescape_url() in server/util.c should be hardened to not write
the null byte when detected.

-- 
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to