https://bz.apache.org/bugzilla/show_bug.cgi?id=70210
Bug ID: 70210
Summary: mod_rewrite prefix_stat() reaches a UNC host before
UNCList is consulted - incomplete "expand UNC
checking" (r1927041), UNCList bypassed on Windows
Product: Apache httpd-2
Version: 2.5-HEAD
Hardware: PC
Status: NEW
Severity: normal
Priority: P2
Component: mod_rewrite
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
On a Windows httpd where UNCList is unset — the default, which denies all UNC
access - a remote unauthenticated user can make the server open an SMB
connection to a host of their choosing, and hold a worker thread for 21 seconds
per request, by sending a request that a server-context RewriteRule maps onto a
UNC path.
Steps to reproduce :
No UNCList directive anywhere in the configuration, so all UNC access is denied
by default.
1. Configure a server-context rewrite whose substitution begins with two
literal slashes.
No rule flags are needed:
RewriteEngine On
RewriteRule ^/v/(.*)$ "//$1"
(The [UNC] flag reaches the same code, and is arguably the more troubling
entry point: it is documented as controlling slash merging only, so an
administrator who sets it has no reason to expect it also removes UNCList from
the path.)
2. Add a control that reaches the same UNC host through the core directory
walk, which r1927041's sibling change in server/core.c does guard:
Alias /alias-unc "//203.0.113.50/share"
3. Request the control. Use an address you do not route to; RFC 5737 space is
ideal:
curl -s -o NUL -w "%{http_code} %{time_total}\n" \
http://127.0.0.1:8099/alias-unc/f.txt
Expected, and observed: 404 in 0.0016 s, and in the error log
AH10504: check_unc: UNC path //203.0.113.50/share/f.txt not allowed by
UNCList
The guard fires. No network traffic is generated.
4. Request the rewrite rule, with a DIFFERENT address - Windows negative-caches
a failed UNC lookup, so reusing the address from step 3 returns instantly and
produces a false negative:
curl -s -o NUL -w "%{http_code} %{time_total}\n" \
http://127.0.0.1:8099/v/203.0.113.61/share/f.txt
Expected if the check applied: sub-millisecond, plus an AH10504 line.
Observed: 21.02 seconds, and NO check_unc line of any kind in the error log
at LogLevel core:trace6, which logs check_unc's own trace output.
5. The unmistakable observable is the pair from steps 3 and 4 side by side:
same UNC target shape, same server, same run - 1.6 ms and an AH10504 denial on
one path, 21 seconds of SMB connection attempt and complete silence from
check_unc on the other. Confirm with a packet capture on port 445 if you want
to see the network activity directly.
Result :
Unprotected RewriteRule ^/v/(.*)$ "//$1" -> prefix_stat
GET /v/203.0.113.61/share/f.txt
21023.7 ms 404
error.log:
mod_rewrite.c(548): local path result: //203.0.113.61/share/f.txt
check_unc log lines for this request: 0
Isolating the cost to one call. Timing apr_filepath_root() directly, via
ctypes, against the same libapr-1.dll the server is running, one fresh address
per row:
apr_filepath_root(..., APR_FILEPATH_TRUENAME, ...)
control: C:/Windows/win.ini 0.0 ms rv=0 root=C:/
\\203.0.113.41\share/f.txt 21038.3 ms rv=20024
(APR_EBADPATH)
//203.0.113.42/share/f.txt 21040.7 ms rv=20024
the same calls WITHOUT APR_FILEPATH_TRUENAME
\\203.0.113.45\share/f.txt 0.0 ms rv=0
root=\\203.0.113.45\share/
//203.0.113.46/share/f.txt 0.0 ms rv=0
root=//203.0.113.46/share/
So the network operation is apr_filepath_root() under APR_FILEPATH_TRUENAME -
it calls filepath_root_test() -> GetDriveTypeW() on the UNC root - and it then
fails, which is why prefix_stat() returns at
modules/mappers/mod_rewrite.c:1012 (2.4.68)
rv = apr_filepath_root(&root, &curpath, APR_FILEPATH_TRUENAME, pool);
if (rv != APR_SUCCESS) {
return 0;
}
before ever reaching the apr_filepath_merge() below it.
ap_filepath_merge()/check_unc() are therefore never invoked, which matches the
zero check_unc log lines above.
--
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]