Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 43 additions & 22 deletions src/pentesting-web/crlf-0d-0a.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,35 +171,56 @@ Moreover, researchers also discovered that they could desync the memcache respon

### Pre-auth Session File Poisoning via CRLF

Some applications **persist session state before authentication completes** and later **reload the same session from disk** after additional requests. If attacker-controlled values from **headers**, **cookies**, or login parameters are written into that session file **without stripping `\r` / `\n`**, CRLF injection can become an **authentication bypass** instead of just response splitting.<sup>[[6]](#references)</sup><sup>[[7]](#references)</sup><sup>[[8]](#references)</sup>
Some applications persist a session **before authentication finishes** and serialize it as line-oriented `key=value` records. If a request-derived value reaches the serializer with `\r` or `\n` intact, the attacker can create additional session keys and turn a CRLF sink into a [login bypass](login-bypass/README.md). The sanitizer must therefore run in the final writer, not only in selected callers.<sup>[[6]](#references)</sup>

Typical exploitation pattern:
#### Optional-secret downgrade

1. A failed or incomplete login **creates a pre-auth session file** on disk.
2. The attacker finds a field that is later written to the session store, commonly a **Basic Authorization** value, a **session cookie subfield**, or another login-related attribute.
3. If the product uses a **structured session identifier** or cookie format, try **removing optional/expected segments** to force a weaker code path where attacker-controlled data is **not encoded/encrypted** before being persisted.
4. Inject raw CRLF so the serialized session becomes **multi-line**, allowing creation of extra trusted entries such as:
Pay special attention to structured session cookies where one component selects the file while another enables encryption or encoding. In the cPanel pattern, `session_id,<secret>` and `session_id` resolve to the **same raw file**, but omitting `<secret>` disables password encoding. Reusing a legitimate pre-authentication identifier without the optional suffix consequently makes embedded CRLF reach the line-oriented file unchanged.<sup>[[6]](#references)</sup>

```text
user=root
cp_security_token=/cpsess...
For example, an injected password beginning with `x\r\n` can produce the following raw records, placing an ordinary password value before the trusted fields required by later authorization checks:<sup>[[6]](#references)</sup>

```ini
pass=x
hasroot=1
tfa_verified=1
user=root
successful_internal_auth_with_timestamp=1
```

5. Trigger a **session reload / resume** path. If the parser trusts the poisoned session file, the attacker upgrades a pre-auth session into an authenticated or privileged one.
Audit this primitive in the following order:<sup>[[6]](#references)</sup>

1. Create a legitimate pre-auth session through a failed or incomplete login.
2. Trace attacker-controlled header, cookie, and login values to the session writer. Basic Authentication is useful because Base64 decoding can recover raw CRLF even when the HTTP header itself remains syntactically valid.
3. Mutate or remove optional cookie components and compare both the selected storage path and the encoding branch.
4. Inject duplicate security-sensitive keys and determine whether the raw parser uses first-value-wins or last-value-wins behavior.

#### Raw-store/cache parser differential

A successful write does not guarantee that normal session loads see the forged keys. Applications may write both a canonical text file and a preferred JSON/binary cache: the text parser interprets CRLF as record boundaries, while the structured serializer preserves it inside one string. This is a **representation desynchronization** and cache-poisoning primitive, distinct from shared HTTP [cache poisoning and cache deception](cache-deception/README.md).<sup>[[6]](#references)</sup>

Look for a reachable error, repair, counter-update, or maintenance path that performs this sequence:<sup>[[6]](#references)</sup>

1. Opens the raw store with a `nocache`-style option.
2. Parses the injected lines into separate map entries.
3. Modifies an unrelated field.
4. Rewrites both the raw store and the preferred cache.

In the cPanel chain, requesting a protected route without its URI security-token prefix reaches the token-denied handler. That handler increments a counter through a session modifier which explicitly reads the raw file and then regenerates the JSON cache. Sanitization at this stage only removes CRLF from the now-short `pass` value; it cannot distinguish and remove the forged keys that the raw parser already promoted into the map.<sup>[[6]](#references)</sup>

After promotion, test whether any injected field is treated as **proof of authentication** rather than merely metadata. A truthy successful-authentication timestamp is especially dangerous when checked before the real password hash: the cPanel authorization path accepted the session timestamp and returned success without consulting `/etc/shadow`. Combining that short circuit with forged user, privilege, and MFA flags upgrades the pre-auth session.<sup>[[6]](#references)</sup>

Quick notes for review and exploitation:
#### Review, detection, and hardening

- Check whether the session store is **line-oriented** (`key=value` per line). These formats are especially sensitive to CRLF.
- Compare how the application handles a **freshly issued session cookie** versus a **malformed/truncated** version of the same cookie.
- If authentication is split across several requests, inspect whether the **same session identifier survives** from the failed login into the later privileged request.
- Newline injection into one field can be enough if the reload logic later trusts **presence of keys** such as `user`, `role`, `successful_external_auth_with_timestamp`, or `tfa_verified`.
Useful code-review and runtime checks for this class of issue include:<sup>[[6]](#references)</sup>

Detection / triage ideas:
- Enumerate every session-writer caller and verify that the writer itself rejects CR/LF in **all** scalar values.
- Treat a missing encoding secret as an error, or encode with a safe unambiguous fallback; never let an optional suffix both disappear during path normalization and silently select weaker storage behavior.
- Compare raw and cached representations and alert when their parsed key sets differ.
- Flag pre-auth sessions containing authenticated-only fields, duplicate privilege/MFA keys, multi-line password values, or authentication timestamps not issued by the authentication subsystem.
- Correlate failed logins and token-denied requests that operate on the same session because an error path may be the cache-promotion gadget.
- Do not authorize based only on the presence or truthiness of mutable session fields; authenticate state with integrity protection and validate timestamp provenance and freshness.

- Inspect pre-auth session files for **authenticated-only keys**.
- Flag session files whose `pass` or equivalent field became **multi-line**.
- Correlate **failed-login origins** with later session records containing valid security tokens or authenticated attributes.
For cPanel/WHM, apply a vendor-fixed build rather than relying on edge filtering: the patch centralizes session-value filtering in the writer and safely transforms the password even when the optional secret is absent.<sup>[[6]](#references)[[7]](#references)</sup>

### How to Prevent CRLF / HTTP Header Injections in Web Applications

Expand Down Expand Up @@ -290,9 +311,9 @@ into a reflected header. If every intermediary preserves the injected fields and
- [3] [PortSwigger Research: Making HTTP header injection critical via response queue poisoning](https://portswigger.net/research/making-http-header-injection-critical-via-response-queue-poisoning)
- [4] [Netsparker: What Is CRLF / HTTP Header Injection?](https://www.netsparker.com/blog/web-security/crlf-http-header/)
- [5] [NVD - CVE-2024-45302 (RestSharp CRLF injection)](https://nvd.nist.gov/vuln/detail/CVE-2024-45302)
- [6] [Rapid7 - CVE-2026-41940: cPanel & WHM Authentication Bypass](https://www.rapid7.com/blog/post/etr-cve-2026-41940-cpanel-whm-authentication-bypass)
- [7] [watchTowr - The Internet Is Falling Down, Falling Down, Falling Down (cPanel & WHM Authentication Bypass CVE-2026-41940)](https://labs.watchtowr.com/the-internet-is-falling-down-falling-down-falling-down-cpanel-whm-authentication-bypass-cve-2026-41940/)
- [8] [cPanel Security Update 04/28/2026](https://support.cpanel.net/hc/en-us/articles/40073787579671-Security-CVE-2026-41940-cPanel-WHM-WP2-Security-Update-04-28-2026)
- [6] [watchTowr Labs - cPanel & WHM authentication bypass research](https://labs.watchtowr.com/the-internet-is-falling-down-falling-down-falling-down-cpanel-whm-authentication-bypass-cve-2026-41940/)
- [7] [cPanel - Critical Vulnerability with cPanel & WHM Login Authentication](https://support.cpanel.net/hc/en-us/articles/40073787579671-Critical-Vulnerability-with-cPanel-WHM-Login-Authentication)
- [8] [Rapid7 - CVE-2026-41940: cPanel & WHM Authentication Bypass](https://www.rapid7.com/blog/post/etr-cve-2026-41940-cpanel-whm-authentication-bypass)
- [9] [Apache HTTPCLIENT-1974: Unicode bypass of HTTP header CR/LF validation](https://issues.apache.org/jira/browse/HTTPCLIENT-1974)
- [10] [Bugbounty: Exploiting CRLF Injection Can Land Into a Nice Bounty](https://medium.com/bugbountywriteup/bugbounty-exploiting-crlf-injection-can-lands-into-a-nice-bounty-159525a9cb62)
- [11] [HackerOne Report #192667 - CRLF injection in the URL path](https://hackerone.com/reports/192667)
Expand Down