
Detailed writeup of CVE-2021-41773 Apache path traversal and RCE exploitation, with step-by-step commands and root cause analysis from a TryHackMe lab environment.
Writeup of the TryHackMe "Modern Web Stacks" room, focused on exploiting CVE-2021-41773, a path traversal vulnerability in Apache HTTP Server 2.4.49 that leads to remote code execution when mod_cgi is enabled.
| Item | Detail |
|---|---|
| Vulnerability | CVE-2021-41773 — Apache 2.4.49 Path Traversal / RCE |
| Target service | Apache HTTP Server on port 8080 |
| Vulnerable version | Apache/2.4.49 (Unix) |
| Root cause | Broken normalization order in ap_normalize_path() |
| Impact | Arbitrary file read → Remote Code Execution via mod_cgi |
| Tools used | curl |
Apache 2.4.49 changed how ap_normalize_path() processes URLs. Apache is supposed to block any request path containing ../ before it reaches the filesystem — but the traversal filter runs before full URL decoding takes place.
This means a request using the double-encoded sequence .%2e/ is not recognized as ../ by the filter. However, once Apache hands the path to the OS, .%2e/ is resolved to ../, and the traversal filter has already been bypassed.
On its own this allows arbitrary file reads outside the web root. The impact becomes critical when combined with mod_cgi: if the traversal path resolves to an executable like /bin/sh inside a CGI-enabled directory (e.g. /cgi-bin/), Apache executes it as a CGI script and passes the HTTP POST body to its stdin — giving remote command execution.
Identified the target's Server response header as:
Apache/2.4.49 (Unix)
This version is directly affected by CVE-2021-41773.
/cgi-bin/ availabilityRequested /cgi-bin/ and received a 403 Forbidden response (not a 404), indicating the directory exists and mod_cgi is likely enabled — a precondition for RCE via this CVE.
Used curl with the --path-as-is flag to send the encoded traversal sequence exactly as typed, without curl normalizing it client-side first:
curl -s --path-as-is "http://<TARGET_IP>:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh" \
--data 'echo Content-Type: text/plain; echo; cat /flag.txt'
Why --path-as-is is required: by default, curl normalizes URLs and strips .%2e/ sequences before the request is even sent. --path-as-is tells curl to send the URL exactly as written, preserving the encoded traversal so it reaches the server intact.
The payload traversed out of /cgi-bin/ to the root filesystem, executed /bin/sh as a CGI script via the injected POST body, and returned the contents of /flag.txt.
Flag format confirmed: THM{...}
(Flag redacted per TryHackMe's guidelines on public writeups.)
mod_cgi + path traversal = RCE. File read alone is bad; combined with a CGI-executable directory, it becomes command execution.--path-as-is (or an equivalent raw-request tool) is essential when testing encoding-based bypasses.mod_cgi unless explicitly required.This writeup documents a lab environment (TryHackMe). No unauthorized systems were accessed.