...

CRITICAL VULNERABILITY ADVISORY  |  ACTIVE EXPLOITATION  |  CISA KEV

Securify

1. The Vulnerability: What Actually Went Wrong

Root Cause — CRLF Injection in Pre-Auth Session Files

The root cause is deceptively simple: cPanel’s cpsrvd daemon creates a session file on disk before authentication succeeds. A failed login — any username, any password — still produces a writable session file under /var/cpanel/sessions/raw/. That file uses a line-delimited key=value format. If user-controlled data reaches the file without CRLF stripping, an attacker can inject arbitrary key-value pairs, including privilege fields like needs_auth=0 and hasroot=1.

A sanitisation function called filter_sessiondata already existed in the codebase. Its job was to strip \r and \n characters from session data before writing. The bug: it was called inconsistently by callers rather than centrally inside saveSession() itself. Some code paths wrote sessions to disk without ever calling it.

Patch Diff — Three Files, One Architectural Fix

WatchTowr Labs diffed the patched (11.110.0.97) and unpatched (11.110.0.96) releases and identified three modified files: Cpanel/Session.pm (the saver), Cpanel/Session/Load.pm (the loader), and Cpanel/Session/Encoder.pm (new hex round-trip primitives). The critical change was moving filter_sessiondata() inside saveSession() itself:

Figure 1 — Actual patch diff from Cpanel/Session.pm. The fix moves filter_sessiondata() inside saveSession(), making CRLF sanitisation mandatory for every code path rather than optional per-caller. Source: watchTowr Labs.

The architectural lesson: security-critical sanitisation must be enforced inside the function that performs the dangerous operation, not left to callers that can forget or be bypassed. This is a recurring pattern in CRLF injection vulnerabilities — and it’s how one missed call path became a CVSS 9.8 zero-day.

2. Exploit Walkthrough: Mechanism Step by Step

Documentation ScopeThis section documents the attack mechanism as analysed by watchTowr Labs, Rapid7, and Cato Networks, and corroborated by forensic artefacts from compromised hosts. HTTP sequences and session file examples reflect published research and honeypot captures. No novel attack capability is disclosed here — all referenced techniques are described in public CVE records, vendor advisories, and peer security research.

Figure 2 — CVE-2026-41940 attack chain: six stages from unauthenticated probe to full WHM root access.

Stage 1 — A Failed Login That Gives Too Much

The attack begins with an entirely ordinary failed login. The attacker does not need valid credentials — any username and password combination triggers the vulnerable code path. What matters is what the server does in response:

Figure 3 — POST to /login/?login_only=1 with invalid credentials. The 401 response still includes a whostmgrsession cookie — the pre-auth session file is now on disk and becomes the injection target.

The 401 is misleading. Authentication failed, but cpsrvd still created a session file and issued a valid session cookie. That cookie value is the session file name. The file is sitting at /var/cpanel/sessions/raw/<session_name> — and it contains user-derived data that was written without CRLF sanitisation.

Stage 2 — Anatomy of a Pre-Auth Session File

Here is what a normal pre-authentication session file looks like. Every field should be server-generated and trustworthy — but the unsanitised password value can inject arbitrary new lines into this format:

Figure 4 — Normal pre-auth session file written by cpsrvd after a failed login. The needs_auth=1 field is the authentication gatekeeper. CRLF injection allows overwriting it with attacker-controlled values.

Stage 3 — What a Compromised Session File Looks Like

This is the defender’s view — what incident responders find when they inspect session files on a compromised server. The injected fields are clearly anomalous compared to any legitimate cPanel session:

Figure 5 — Forensic IoC: compromised session file with attacker-injected fields. The presence of hasroot=1 in any cPanel session file is an immediate indicator of compromise — it is not a standard session field.

Any session file containing hasroot=1 should be treated as an immediate indicator of compromise. It is not a standard cPanel session field. Its presence means an attacker successfully wrote arbitrary data to the session file via CRLF injection.

Stage 4 — Full WHM Root Access, No Password

Once the session file contains the forged privilege fields, the next request using that session cookie is processed as an authenticated root session. cpsrvd reads the file, sees needs_auth=0 and hasroot=1, and grants full administrative access without any further validation:

Figure 6 — WHM JSON API responds as root with full account listing. At this point the attacker has complete server control: all databases, DNS records, SSL private keys, hosted accounts, and the ability to deploy further payloads.

Blast Radius on Shared HostingA single cPanel/WHM server typically hosts tens to hundreds of customer sites. Compromising WHM means compromising every account on that server — not just the hosting provider’s infrastructure, but all their customers’ data, email, and web presence. The blast radius of one exploit is multiplied by every hosted account.

3. Active Exploitation — Lab Validation & PoC Evidence

The following demonstrates CVE-2026-41940 as tested in a controlled lab environment against an unpatched cPanel/WHM instance (11.134.0.17, running on a dedicated test server with no production data). All IP addresses and identifying information in the screenshots have been redacted. The purpose is to show what exploitation looks like from a defender’s monitoring and detection perspective.

Lab EnvironmentAll testing was conducted in an isolated, privately-owned cPanel/WHM instance running version 11.134.0.17 on a cloud VM with no customer data. Target IPs are redacted in all screenshots. No production systems, customer data, or third-party infrastructure was accessed.

Step 1 — Identifying Exposed cPanel/WHM Instances

Before running any exploit, the attacker (or a defender running an exposure audit) identifies hosts with cPanel/WHM admin ports internet-accessible. The standard discovery approach uses nmap against the four cPanel management ports:

Figure 7 — nmap scan identifying hosts with WHM port 2087 open on the public internet. In a real attacker scenario, this would be run against a /24 or CIDR range from Shodan/Censys data. Defenders should run this against their own IP ranges as an exposure audit.

Step 2 — Confirming Vulnerable Version

cPanel’s /json-api/version endpoint is accessible without authentication and returns the exact build version. Comparing against the patched thresholds per release track confirms whether a target is vulnerable before any exploit attempt:

Figure 8 — Unauthenticated version fingerprint via the cPanel JSON API. Version 11.134.0.17 is below the patched threshold (11.134.0.20) — confirmed vulnerable. Version 11.134.0.21 is patched — skip.

Step 3 — Vulnerability Scan: cpanel2shell-scanner

With the target confirmed unpatched, the next step in a real attack (or a penetration test) is running a targeted scanner to confirm exploitability. cpanel2shell-scanner (scanner.py) is a lightweight PoC scanner purpose-built for CVE-2026-41940 that probes both the cPanel port (2083) and the WHM port (2087) simultaneously and reports whether each endpoint is vulnerable to the authentication bypass. The following output is from our lab run against the test instance:

Figure 9 — Lab evidence: cpanel2shell-scanner output. Port 2083 is NOT VULNERABLE (patched or mitigated). Port 2087 (WHM) is confirmed VULNERABLE to CVE-2026-41940. Summary: scanned=2, vulnerable=1, not_vulnerable=1, connection_failed=0. IP addresses redacted.

The scanner output is intentionally terse — [!] VULNERABLE vs [+] NOT VULNERABLE per port — designed for fast bulk triage across large IP ranges. A single VULNERABLE result on port 2087 (WHM) is sufficient confirmation to proceed to session exploitation. Port 2083 returning NOT VULNERABLE on the same host reflects version-level differences in how individual service endpoints were patched.

Step 4 — Post-Session Checker: cPanelSniper Full Auth Bypass Confirmed

With vulnerability confirmed by cpanel2shell-scanner, the next stage uses cPanelSniper (check_session.py, by Yusuf Mert Roztas — GitHub: ynsmroztas/cPanelSniper) to perform the actual CRLF injection, forge a privileged session, and validate authenticated access across multiple WHM API endpoints. This tool goes beyond simple detection — it executes the full bypass chain and confirms whether a forged session achieves real API-level authentication. This is the output from our controlled lab run:

Figure 10 — Lab evidence: cPanelSniper (check_session.py) output against the vulnerable WHM target. Full 6-stage execution: [1] pre-auth session minted (session base :ghGgqOXIiIGn2unvs), [2] CRLF injection via Basic auth + no-ob cookie (HTTP 307), [3] do_token_denied propagation (HTTP 401 — expected), [4] session auth check across WHM endpoints — /json-api/version and /json-api/applist return HTTP 200 [AUTH_OK]. Final result: SESSION IS AUTHENTICATED. Access URL and forged session cookie printed. IP addresses redacted.

Breaking down what the cPanelSniper output tells us about the attack mechanism at each stage:

cPanelSniper StageWhat’s Happening Under the Hood
[1] Minting pre-auth sessionA failed login POST is sent to /login/?login_only=1. cpsrvd returns HTTP 401 but still creates a pre-auth session file on disk and issues a whostmgrsession cookie. The session base (e.g. :ghGgqOXIiIGn2unvs) is the on-disk file that will be targeted for injection.
[2] CRLF injection via Basic auth + no-ob cookiecPanelSniper injects CRLF-delimited key=value pairs through the no-ob session code path in saveSession() — the specific branch in Cpanel/Session.pm that was missing the filter_sessiondata() call before patching. The HTTP 307 redirect is expected and confirms the injection reached the session file write path.
[3] do_token_denied propagation (HTTP 401)A token propagation request returns HTTP 401. This is expected — it is part of the multi-stage bypass flow, not a failure. The session is not yet fully resolved at this point in the chain.
[4] Session auth check — WHM endpointscPanelSniper validates the forged session against multiple WHM API endpoints. HTTP 503 on the WHM home page and terminal are server-side restrictions. HTTP 200 [AUTH_OK] on /json-api/version and /json-api/applist confirms root-level API authentication — the forged session is fully accepted.
[+] SESSION IS AUTHENTICATEDFull authentication bypass confirmed. The WHM browser URL and forged session cookie are printed for direct browser access. The attacker now has root WHM access with no valid credentials used at any stage.

The tool output also provides the WHM browser URL and the exact session cookie needed to access the WHM dashboard directly in a browser — confirming the attack results in a fully usable administrative session, not just an API token.

What an Attacker Does NextWith root WHM access confirmed, real-world attackers observed in the April–May 2026 campaigns took several post-exploitation paths: creating new admin/reseller cPanel accounts for persistent re-entry; exfiltrating SSL private keys, database credentials, and email archives; deploying the ‘Sorry’ Go-based ransomware encryptor across all hosted site directories; planting SSH keys and hidden cron jobs (/usr/local/bin/.netmon/beacon) for persistence after cleanup; and in state-linked campaigns, establishing C2 footholds for longer-term espionage operations.

4. Real-World Impact — What Actually Happened

By the time cPanel published their advisory on April 28, 2026, the vulnerability had been exploited as a zero-day for at least two months. KnownHost confirmed exploitation dating to February 23, 2026. The actual window may have been longer.

Figure 11 — Malicious cPanel/WHM hosts detected by Censys and GreyNoise: spiked from ~120 at disclosure (Apr 29) to 18,500 at peak (May 2), driven by ransomware campaigns and Mirai botnet recruitment.

SourceFinding
Shadowserver44,000 unique IPs scanning/exploiting honeypots on April 30, 2026
Censys8,859 hosts with open dirs showing .sorry files; 7,135 confirmed cPanel/WHM
Censys (May 1)~80% of newly malicious hosts were running cPanel/WHM — sharp break from baseline
Rapid7 / Shodan~1.5 million cPanel instances internet-exposed at time of disclosure
Ctrl-Alt-IntelState-linked actor targeting Philippines military (*.mil.ph) and Laos govt (*.gov.la)

The ‘Sorry’ Ransomware Campaign

Figure 12 — Forensic view: .sorry extension ransomware files across cPanel hosting directories. Censys confirmed 7,135 cPanel/WHM hosts publicly exposing encrypted files in open web directories.

The dominant post-exploitation payload was a Go-based Linux encryptor deploying the ‘Sorry’ ransomware strain. Post-compromise profile on affected servers:

  • Files encrypted with ChaCha20 + RSA-2048 key wrapping
  • All encrypted files given a .sorry extension (wp-config.php → wp-config.php.sorry)
  • README.md ransom note dropped with Tox contact ID for decryption negotiation
  • Server-side backups wiped to prevent local recovery
  • SSH keys, hidden cron jobs (/usr/local/bin/.netmon/beacon), and sudoers backdoors planted for re-entry

8,859 of these servers had their encrypted files in publicly browseable open directories — visible to anyone on the internet, triggering breach notification obligations in most jurisdictions regardless of whether a ransom was paid.

State-Linked Espionage

Ctrl-Alt-Intel identified a separate campaign from IP 95.111.250[.]175 targeting Philippine military and Laotian government domains — using public CVE-2026-41940 PoC code alongside a custom exploit chain for an Indonesian defence sector portal. This was not opportunistic ransomware. The cPanel exploit was part of a pre-positioned toolkit.

CISA KEV — Added May 1, 2026CVE-2026-41940 was added to CISA’s Known Exploited Vulnerabilities catalog on May 1, 2026. Federal agencies under BOD 22-01 were mandated to patch by May 3. For commercial operators, CISA KEV status is increasingly treated by auditors and insurers as a standard-of-care baseline.

5. Detection: Finding the Compromise

Two complementary approaches: the official cPanel detection script and manual session file inspection. Run both — the official script had a false positive issue in its first release that an updated version addressed, and manual inspection catches things the script may miss.

Figure 13 — Detection script output from a compromised server. The combination of needs_auth=0, non-standard hasroot=1, and source IP 95.111.250.175 (confirmed IoC) is a high-confidence compromise indicator.

# 1. Official cPanel detection script curl -s https://docs.cpanel.net/scripts/detect-compromise.sh | bash   # 2. Manual check for injected session fields grep -rl 'hasroot' /var/cpanel/sessions/raw/ grep -rl 'needs_auth=0' /var/cpanel/sessions/raw/   # 3. Check for .sorry ransomware files find /home -name '*.sorry' 2>/dev/null | wc -l   # 4. Check for planted SSH backdoor keys cat /root/.ssh/authorized_keys   # 5. Hunt cron persistence crontab -l -u root ls -la /usr/local/bin/.netmon/ 2>/dev/null   # 6. Check for suspicious session source IPs in WHM access logs grep '95.111.250.175' /usr/local/cpanel/logs/access_log
If IoCs Are Present: Patching Is Not EnoughPatching a compromised server leaves all attacker persistence in place: planted SSH keys, hidden cron jobs, API tokens, sudoers backdoors. The safest path after confirmed compromise is rebuilding from a verified pre-compromise backup. Document all IoCs before wiping — IP addresses, session file contents, cron entries, and unknown SSH keys — for incident response and any required breach notifications.

6. Why Organizations Got Caught Flat-Footed

No Inventory of Internet-Exposed Management Interfaces

Many organizations had no clear asset inventory for which servers were exposing ports 2083, 2087, 2095, or 2096 to the public internet. Without that inventory, you cannot respond to a CVSS 9.8 advisory in hours — which is the actual window available before active exploitation hits your infrastructure.

Auto-Update Disabled Without a Compensating SLA

cPanel’s auto-update mechanism was disabled by many providers for operational stability. Reasonable tradeoff normally. During an active exploitation event with a public PoC, it’s a liability. Teams without a manual patch SLA for critical CVEs were caught mid-exploitation.

Admin Ports Open to the Public Internet

There is very rarely a legitimate reason for WHM (2087) and cPanel (2083) to be accessible from the entire public internet without IP restriction. Most administrators access these from known IP ranges. Blanket exposure was the single most common configuration factor among compromised hosts.

No WAF Coverage for Pre-Auth Surfaces

Cloudflare released an emergency WAF rule on April 30 — two days after the advisory. Organizations with WAF coverage got virtual patching before they could apply the cPanel update. Organizations without it had no compensating control in the window that mattered most.

Vendor Notification Failure

The vulnerability was reportedly submitted to cPanel approximately two weeks before the April 28 advisory, with an initial response suggesting nothing was wrong. Hosting providers received no advance notification. The practical result: managed hosting providers and their customers found out at the same time as the public — while exploitation was already underway.

7. Remediation

Patch Versions

Release TrackMinimum Safe Version
110.0.x11.110.0.97
118.0.x11.118.0.63
126.0.x11.126.0.54
132.0.x11.132.0.29
134.0.x11.134.0.20
136.0.x11.136.0.5
# Verify current version /usr/local/cpanel/cpanel -V   # Restart services after patching systemctl restart cpanel cpaneld # or: /scripts/restartsrv_cpsrvd 

Emergency Network Mitigations (If Patch Not Yet Applied)

# Block cPanel/WHM admin ports from the public internet # Allow only from known admin IP ranges — never 0.0.0.0/0 iptables -I INPUT -p tcp --dport 2087 -j DROP   # WHM iptables -I INPUT -p tcp --dport 2083 -j DROP   # cPanel SSL iptables -I INPUT -p tcp --dport 2095 -j DROP   # Webmail iptables -I INPUT -p tcp --dport 2096 -j DROP   # Webmail SSL   # Emergency: stop services entirely if needed systemctl stop cpsrvd cpdavd 

Longer-Term Hardening

  • Restrict ports 2083, 2087, 2095, 2096 to known management IP ranges at the firewall or security group level.
  • Enable cPanel auto-update for security patches, or establish a documented SLA — critical CVEs patched within 24 hours of release.
  • Deploy a WAF in front of cPanel management interfaces for virtual patching coverage on future CVEs.
  • Monitor /var/cpanel/sessions/raw/ for anomalous fields — hasroot, needs_auth=0, sessions from unexpected source IPs.
  • VPN-gate WHM access entirely — there is almost never a legitimate reason it needs to be on the open internet.
  • Maintain offline, verified backups. The Sorry ransomware wiped server-side backups on every compromised host.

Leave a Reply