
CVE-2026-41940 cPanel/WHM auth bypass IOC scanner — fixes false positives in upstream detection script, adds log cross-correlation
Detection script for the cPanel/WHM authentication bypass (CVE-2026-41940) affecting all cPanel versions after 11.40.
This is a rewrite of the upstream cPanel detection script with fixes for false positives and added log correlation.
Scans /var/cpanel/sessions/raw/ for session files that show signs of newline-injection exploitation, then cross-references suspect IPs and session tokens against cPanel access/login/error logs. Also scans the access_log for historical exploitation where the session file has since expired or been purged.
pass regex that false-positives on every authenticated session in production (the regex matches any pass= field followed by another line, which is every session file).method=badpass origin + ANY post-auth attribute instead of requiring the narrow token_denied + cp_security_token combo. Catches PoC variants that omit token_denied.POST /login/?login_only=1 -> 401) with subsequent successful cpsess token usage from the same IP.--extended mode for deeper log sweep across additional sources.# Bash — works everywhere, no dependencies
bash <(curl -fsSL https://raw.githubusercontent.com/AndreiG6/cpanel-cve-2026-41940-ioc/main/ioc.sh)
# Python — faster on large session dirs, supports --json
curl -fsSLo /tmp/ioc.py https://raw.githubusercontent.com/AndreiG6/cpanel-cve-2026-41940-ioc/main/ioc.py
python3 /tmp/ioc.py
# Extended scan (either variant)
bash <(curl -fsSL https://raw.githubusercontent.com/AndreiG6/cpanel-cve-2026-41940-ioc/main/ioc.sh) --extended
python3 /tmp/ioc.py --extended
# Check exit code after run ($? = 0 clean, 1 IOCs found, 2 env error)
echo $?
curl flags:
-ffail on HTTP errors instead of piping an error page into bash,-ssilent (no progress bar),-Sstill show errors despite-s,-Lfollow redirects.
The Python variant supports --json for structured output you can pipe into jq, feed into a SIEM, or process programmatically.
# Full JSON output
python3 ioc.py --json
# Just the summary counts
python3 ioc.py --json | jq '.counts'
# List all CRITICAL findings
python3 ioc.py --json | jq '[.findings[] | select(.severity == "CRITICAL")]'
# Extract unique attacker IPs
python3 ioc.py --json | jq '.suspect_ips[]'
# Show findings with their source IPs (for firewall blocklists)
python3 ioc.py --json | jq '[.findings[] | {severity, source_ip, token: .cp_security_token}]'
# Get all IPs that had successful token usage (for immediate blocking)
python3 ioc.py --json | jq '[.findings[] | select(.severity == "CRITICAL") | .source_ip] | unique'
# Feed cross-ref data for a specific IP
python3 ioc.py --json | jq '.cross_ref[.suspect_ips[0]]'
Example JSON structure:
{
"findings": [
{
"severity": "CRITICAL",
"file": "/var/cpanel/sessions/raw/:Q3f8Ag2epeBuTaIZ",
"verdict": "Injected token used successfully (2xx/3xx in access_log)",
"origin": "address=203.0.113.50,app=whostmgrd,method=badpass",
"source_ip": "203.0.113.50",
"user": "root",
"hasroot": "1",
"tfa_verified": "0",
"cp_security_token": "/cpsess04396539398",
"token_denied": "1",
"successful_internal_auth_with_timestamp": "9999999999",
"token_hits": [
"203.0.113.50 - root [04/30/2026:12:12:01 -0000] \"GET /cpsess04396539398/json-api/version HTTP/1.1\" 200 0 ..."
]
},
{
"severity": "MEDIUM",
"file": "/var/cpanel/sessions/raw/:2TDiaHwh_r8qOH5y",
"verdict": "Injection landed; token was tried but BLOCKED (all 4xx/5xx)",
"source_ip": "198.51.100.23",
"cp_security_token": "/cpsess5637704041",
"token_hits": [
"198.51.100.23 - root [04/30/2026:04:08:09 -0000] \"GET /cpsess5637704041/json-api/version HTTP/1.1\" 403 0 ..."
]
},
{
"severity": "CRITICAL",
"file": null,
"verdict": "Injected cpsess token used with 2xx/3xx after failed login; session expired or purged",
"source_ip": "203.0.113.99",
"cp_security_token": "/cpsess8705792557",
"token_hits": ["..."]
}
],
"counts": {"critical": 2, "high": 15, "medium": 71, "warning": 0},
"suspect_ips": ["203.0.113.50", "198.51.100.23", "203.0.113.99"],
"suspect_ips_omitted": 0,
"cross_ref": {
"203.0.113.50": {
"cpanel_access_log": ["...last 5 lines..."],
"cpanel_login_log": ["..."]
}
},
"advisory": "https://support.cpanel.net/hc/en-us/articles/40073787579671"
}
git clone https://github.com/AndreiG6/cpanel-cve-2026-41940-ioc.git
cd cpanel-cve-2026-41940-ioc
# Bash variant
bash ioc.sh # default (CRITICAL/HIGH expanded, MEDIUM/WARNING counts only)
bash ioc.sh -v # verbose (expand all findings)
bash ioc.sh --extended # verbose + deeper logs + all IPs in cross-ref
# Python variant (same detection logic, faster, structured output)
python3 ioc.py # default (same collapse behavior as bash)
python3 ioc.py -v # verbose
python3 ioc.py --extended # verbose + deeper logs
python3 ioc.py --json # structured JSON (always includes all findings)
Must be run as root on the target cPanel server. Python variant requires Python 3.6+ (ships with CentOS 7 / CloudLinux 7+).
| Code | Meaning |
|---|---|
| 0 | No indicators found |
| 1 | IOCs detected |
| 2 | Environment error (not a cPanel server) |
MIT