Web Security

cPanel CVE-2026-41940: A CRLF Injection That Owns 1.5 Million Hosts

On April 28, 2026, cPanel pushed an emergency update for what its release notes called "an issue with session loading and saving." The next day, VulnCheck assigned CVE-2026-41940 with a CVSS of 9.8. By April 30, Shadowserver was tracking 44,000 IP addresses scanning and brute-forcing honeypots looking for vulnerable instances. By May 2, Ctrl-Alt-Intel was reporting confirmed compromises against government, military, and managed-service-provider targets in Southeast Asia and a smaller cluster across the Philippines, Laos, Canada, South Africa, and the United States. KnownHost has since disclosed that exploitation in the wild predates the patch by roughly two months — meaning CVE-2026-41940 was a true zero-day from late February through April 28.

cPanel and WebHost Manager (WHM) sit underneath an estimated 70 million domains, with roughly 1.5 million internet-exposed control panels per Shodan telemetry referenced by Rapid7. CVE-2026-41940 is a pre-authentication, network-reachable bug. There is no privilege required, no user interaction, no special configuration. If WHM port 2087 or cPanel port 2083 is reachable on the public internet and the server is on any version after 11.40 prior to the April 28 patches, an attacker can become root on that server with a single sequence of HTTP requests. CISA added it to the Known Exploited Vulnerabilities catalog within days. Multiple threat actors are using the same exploit to deface websites, encrypt data, and stand up persistence.

This is the kind of bug that defines a quarter for the hosting and MSP ecosystem. If your organization runs cPanel — or relies on a vendor that does — the next 72 hours determine whether you are a footnote in a forensic timeline or not.

How the exploit works

The technical writeup that has held up best is from Picus Security, building on Trend Micro's analysis. The bug is a chain of two weaknesses, neither of which would be catastrophic on its own.

The first weakness is a Carriage Return Line Feed (CRLF) injection in the way cPanel processes the password field of an HTTP Basic Authentication header. When a login attempt fails, the server still writes a session file to disk with the credentials the attacker submitted. If the password contains raw \r\n sequences, the session writer does not sanitize them. The attacker controls additional lines in the on-disk session file — and those additional lines are interpreted as session attributes when the file is read back.

The second weakness is in how cPanel stores session state. Each session is held in two places: a raw text file written line-by-line, and a JSON cache used during the actual authentication check. Under normal conditions, the encrypted JSON cache is the source of truth. Under specific conditions — namely, sending a follow-up request with a malformed cookie that omits the encryption-key segment — cPanel falls back to re-parsing the raw text file and overwriting the JSON cache from it. That re-parse pulls in the attacker's injected lines and promotes them to top-level session attributes.

The injected attributes include a flag the codebase reads as "this session is already authenticated, skip the password check," along with a flag that marks the session as root. After two requests, an attacker who never had a valid credential is treated as the root user of the WHM control panel. From there, every cPanel API endpoint is available — file system access, MySQL credentials, DNS configuration, every customer's home directory, every cron job.

The mechanic is a textbook violation of a basic principle that Picus calls out cleanly: "A flag that means 'trust me, I already checked' must be cryptographically bound to the thing that actually checked." cPanel's authentication layer trusted a session attribute that any pre-auth caller could plant on disk. Once you understand that, the exploit is mechanical.

Why MSPs and hosting providers are the soft target

The scanning data tells a clear story about who is being hit first. Shadowserver's honeypot telemetry showed exploitation traffic concentrated against MSPs and hosting providers in the Philippines, Laos, Canada, South Africa, and the United States. There are three reasons for that targeting pattern, and they all matter for SMB defenders even if you do not directly run cPanel yourself.

First, MSPs and hosting providers are the highest-density targets. A single compromised cPanel server may host 50 to 500 customer accounts. If the customer accounts are SMB websites, e-commerce checkout pages, or law-firm portals, root on the cPanel host is root on every one of them. The attack pays for itself many times over.

Second, MSP and hosting-provider cPanel instances are almost always internet-exposed by design. The whole point of the panel is that resellers, technicians, and customers can reach it from anywhere. Network segmentation is not a normal control here. The attack surface is the internet.

Third, patching at MSPs is harder than at end customers. The MSP cannot just take an outage window unilaterally — they have customer service-level agreements to respect. cPanel's patch requires running /scripts/upcp --force and a service restart. Many MSPs deferred the patch by hours or days while they coordinated communications with customers. Two months of zero-day exploitation plus a patching gap is exactly the window an opportunistic operator wants.

If your business does not run cPanel directly but your website, email, or e-commerce backend is hosted by a vendor that does, this is the right week to ask the vendor a direct question: "When did you patch CVE-2026-41940 on every server that touches our data, and what evidence of compromise have you reviewed?" The answer should be specific. If it is not, treat your hosted assets as potentially compromised until the vendor produces a clear timeline.

What to do this week

Layer 1: Patch every cPanel and WP Squared instance

The fixed versions are tightly tied to the major-version stream. Run the cPanel update command and confirm afterward that the running version matches the patched build for your stream:

# Force-run the cPanel update to pick up the patched build
/scripts/upcp --force

# Confirm the patched version
/usr/local/cpanel/cpanel -V

# Patched versions per major stream:
# 11.86.0.41
# 11.110.0.97
# 11.118.0.63
# 11.126.0.54
# 11.130.0.19
# 11.132.0.29
# 11.134.0.20
# 11.136.0.5
# WP Squared: 136.1.7

# If the server runs an unsupported version (<= 11.40 lineage left behind),
# upgrade to a supported stream first. Servers on EOL versions are not
# eligible for security updates.

Verify on every server you administer, not just the production fleet. Staging, reseller-only, and "internal only" cPanel boxes have all been observed in the exploitation telemetry. Anything reachable on TCP/2083 or TCP/2087 is in scope.

Layer 2: Reduce exposure while patching is in flight

cPanel and Namecheap both recommended restricting access to ports 2083 and 2087 during the emergency window. Even after patching, this is a control that should have been in place. The panel does not need to be reachable from the entire internet — it needs to be reachable from your operations team, your resellers, and a defined set of customer locations.

# Restrict cPanel/WHM ports to a defined allowlist using firewalld
# (replace 203.0.113.0/24 with your operations network)
firewall-cmd --permanent --new-zone=cpanel-admin
firewall-cmd --permanent --zone=cpanel-admin --add-source=203.0.113.0/24
firewall-cmd --permanent --zone=cpanel-admin --add-port=2083/tcp
firewall-cmd --permanent --zone=cpanel-admin --add-port=2087/tcp
firewall-cmd --permanent --zone=public --remove-port=2083/tcp
firewall-cmd --permanent --zone=public --remove-port=2087/tcp
firewall-cmd --reload

# Or with iptables
iptables -A INPUT -p tcp --dport 2083 -s 203.0.113.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 2087 -s 203.0.113.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 2083 -j DROP
iptables -A INPUT -p tcp --dport 2087 -j DROP

For MSP customer-facing access where an IP allowlist is not workable, put the panel behind an authenticated reverse proxy or a zero-trust access broker (Cloudflare Access, Tailscale, similar). The goal is the same: do not let the panel's authentication layer be the first thing the public internet talks to.

Layer 3: Hunt for compromise

Because exploitation predates the patch by roughly two months, the question is not just "are we patched" but "did we get popped between late February and the day we patched." There are a few high-signal indicators to check.

The session writer leaves traces. Sessions written via the exploit contain the injected key-value pairs in the raw session file even after the attacker has moved on. Look for unexpected attributes in /var/cpanel/sessions/:

# Hunt for suspicious session files containing CRLF-injected attributes
# Look for sessions with unexpected "authenticated" or "root" markers,
# or unusual ratios of fields
find /var/cpanel/sessions/ -type f -newer /tmp/feb15_marker -mtime -90 \
    -exec grep -lE "(authenticated|verified|root|skip_password)" {} \;

# Look for sessions with raw \r\n in unexpected places
find /var/cpanel/sessions/ -type f -mtime -90 \
    -exec grep -lP '\r\n[a-z_]+=' {} \;

# Sessions with extreme line counts vs typical ~5-10 lines
find /var/cpanel/sessions/ -type f -mtime -90 \
    -exec sh -c 'wc -l "$1" | awk "{if (\$1 > 30) print \$2}"' _ {} \;

The login telemetry matters too. Look at /usr/local/cpanel/logs/login_log and the access logs for HTTP Basic Auth attempts where the password field contains URL-encoded %0d%0a sequences, or for unexplained successful logins from IPs that have never authenticated before. The absence of a corresponding password-reset event around a successful root login is itself an indicator.

# Hunt for CRLF-injection signatures in access logs
grep -E "(%0d%0a|%0D%0A)" /usr/local/apache/logs/access_log
grep -E "(%0d%0a|%0D%0A)" /var/log/cpanel-install*.log

# Look for successful root logins from new IPs
awk '$0 ~ /SUCCESSFUL LOGIN/ && $0 ~ /root/' /usr/local/cpanel/logs/login_log | \
    awk '{print $NF}' | sort -u

# Compare against historical login IPs to flag new sources
last -i | grep root | awk '{print $3}' | sort -u > /tmp/historical_root_ips.txt

Beyond the panel itself, hunt for the post-exploitation patterns Help Net Security and Cybersecurity Dive have observed in the wild: defacements (recent modifications under /home/*/public_html/ or /usr/local/apache/htdocs/), unexpected cron jobs (crontab -l for every account, plus /etc/cron.d/ and /var/spool/cron/), new SSH keys in ~/.ssh/authorized_keys across all home directories, and unfamiliar processes listening on non-standard ports.

Layer 4: Rotate everything the panel could have touched

If you find evidence of compromise — or if you cannot rule it out — rotate. cPanel root access is everything access. The list, in priority order:

  • Server root password and any sudoer accounts on the host.
  • SSH keys for root and for every cPanel user account on the host.
  • MySQL root password and per-account database passwords.
  • API tokens issued through WHM.
  • Email account passwords for every cPanel user (a compromised panel exposes /etc/cpanel/ea4/ and the underlying mail spool).
  • FTP and SFTP credentials for every customer account.
  • Any credentials hardcoded in customer applications under /home/*/public_html/ — database connection strings, API keys, payment processor secrets.

For MSPs, the customer communication needs to be specific. "We patched this week" is not enough. Customers whose data could have been touched during the exploitation window need to know what was potentially exposed and what they should rotate on their end.

The pattern beyond cPanel

CVE-2026-41940 is a particular kind of bug, and the pattern is worth naming because it will keep recurring. Authentication systems that store state on disk in two formats — a raw text file and a structured cache — are inherently fragile. The race between "what was written" and "what gets parsed" is exactly where this exploit lives. SimpleHelp's CVE-2024-57726 in late April was a different mechanic but the same family of failure: a privileged operation that trusted attacker-influenced state. The pattern shows up in WordPress plugins, in legacy Java application servers, in printer firmware, in network device admin panels.

The defensive lesson is to stop trusting the network perimeter to filter the panel. Internet-exposed admin interfaces — cPanel, Plesk, WordPress wp-admin, Webmin, ConnectWise ScreenConnect, Jenkins, Argo CD, every SaaS-style admin console you self-host — are pre-auth attack surface. Each one needs an outer layer of authentication that you control, an allowlist or zero-trust proxy that limits who can even reach the login page, and a monitoring path that distinguishes "successful login from a known location" from "successful login that came out of nowhere." That posture would not have prevented CVE-2026-41940. It would have made the difference between an emergency triage week and a footnote.

If your last conversation with your hosting provider or MSP about their security posture was a sales call, this is the right week to make it a real conversation.

The hunt commands above are the starting point. The harder question is what is on your perimeter that you do not know about.

Red Hound's external recon engagements use open-source tooling — nuclei templates for cPanel/WHM/Plesk/SimpleHelp/ScreenConnect fingerprinting, masscan-driven exposure mapping, and a vendor risk checklist tailored to your hosting and MSP relationships. The tooling is public. We just run it on your behalf, on a schedule, with a written report you can hand to your board. Book a 30-minute walkthrough on what your external attack surface actually looks like today.