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]