Skip to content
THE HUNTER’S LEDGER
Detection Rules · May 17, 2026

Detection Rules — CVE-2026-41940 cPanel Harvester Toolkit — 216.126.227.49

Contents
MITRE ATT&CK coverage — 8 techniques across 5 tactics
Tactic / TechniqueNameRules
Resource Development / T1583.008MalvertisingOperator Parklogic TDS Landing URL Shape (SIGMA, Hunting)
Resource Development / T1587.001MalwareCVE-2026-41940 cPanel Harvester Toolkit: Bespoke Component Filenames (YARA, Detection)
Resource Development / T1588.005ExploitsCVE-2026-41940 cPanel Harvester Toolkit: Bespoke Component Filenames (YARA, Detection)
Initial Access / T1190Exploit Public-Facing ApplicationCVE-2026-41940 cPanel WHM Proxy-Subdomain Admin Path Request (SIGMA, Hunting); CVE-2026-41940 Expired Session Marker in Query String (SIGMA, Hunting); CVE-2026-41940 cPanel WHM Proxy-Subdomain Admin Path Request With HTTP 200 Response (SIGMA, Hunting); Null Byte or Encoded CR/LF After the Base64 Run in an Authorization Basic Header (CVE-2026-41940 Candidate) (SURICATA, Detection)
Persistence / T1098.004SSH Authorized KeysSSH Authorized Keys File Written Under Root or Home Directories by a Process Outside the OpenSSH Tools (SIGMA, Hunting)
Persistence / T1136.001Local AccountPost-Exploitation File Event Under /var/cpanel/users/ From a Process Outside cPanel's Own Directories (SIGMA, Hunting)
Credential Access / T1212Exploitation for Credential AccessCVE-2026-41940 cPanel WHM Proxy-Subdomain Admin Path Request (SIGMA, Hunting); CVE-2026-41940 Expired Session Marker in Query String (SIGMA, Hunting); CVE-2026-41940 cPanel WHM Proxy-Subdomain Admin Path Request With HTTP 200 Response (SIGMA, Hunting); Null Byte or Encoded CR/LF After the Base64 Run in an Authorization Basic Header (CVE-2026-41940 Candidate) (SURICATA, Detection)
Command and Control / T1071.001Web ProtocolsOperator Flask C2 Dashboard Request URI Containing /login-2fa (SIGMA, Hunting); Operator Flask C2 Dashboard Banner Hunt: Werkzeug/3.1.8 + /login-2fa (SURICATA, Hunting)

Campaign: OpenDirectory-CVE-2026-41940-cPanel-Harvester-216.126.227.49 Date: 2026-05-17 Author: The Hunters Ledger License: CC BY 4.0 Reference: https://the-hunters-ledger.com/reports/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517/


Detection Coverage Summary

This campaign centers on CVE-2026-41940, a pre-authentication CRLF-injection auth-bypass in cPanel/WHM, weaponized by an unattributed operator running a Python/Bash credential-harvesting and phishing-distribution toolkit from AS14956 RouterHosting infrastructure. Coverage below spans the CVE exploitation mechanic at the network and log layers, the operator’s live C2 dashboard banner, and forensic identification of the toolkit itself.

Rule Type Detection Hunting MITRE Techniques Covered Atomics → feed
YARA 1 0 T1587.001, T1588.005 0
Sigma 0 7 T1190, T1212, T1071.001, T1583.008, T1098.004, T1136.001 2
Suricata 1 1 T1190, T1212, T1071.001 1

Detection vs Hunting: Detection rules are high-fidelity and evasion-resilient, safe to alert on. Hunting rules are broader, for scoping and threat-hunting. Expect to review the hits.

Highest-confidence anchors:

  • The Suricata network signature flags a null byte or a URL-encoded CR/LF that follows the Base64 credential run in an Authorization: Basic header, a malformed credential that a well-formed Basic header cannot contain, so benign hits should be near zero. Whether the public exploit places its control bytes there, and not inside the Base64 text where this rule cannot see them, has not been established by a retained capture, so the rule is not claimed to detect the exploit (Suricata Detection).
  • The YARA filename-combination rule requires 2-of-7 bespoke, operator-coined component names together, a genuine content signature for forensic/IR identification of the toolkit (YARA Detection).

Atomics routed to the IOC feed: the operator’s Parklogic TDS affiliate account ID pkAId=2143526812 is a rotatable literal, a Sigma rule and a Suricata signature that keyed solely on it are cut and preserved in opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517-iocs.json. A third rule targeting the /f/<12-hex> phishing payload-fetch path is also cut. Its real precision came entirely from a 13-domain allowlist already BLOCK-listed individually in the feed, with no independent value once the domain scoping is removed. See Coverage Gaps for detail.

Evidence posture note: the operator’s toolkit source code was never persisted to disk, so byte-level YARA content signatures against the toolkit’s internals are not possible; the retained YARA rule is a bespoke-filename identification aid for forensic/IR use, not a content signature. Across the remaining rule types, the Suricata CRLF-injection signature is this campaign’s only Detection-tier rule for the CVE itself (it observes the actual exploitation mechanic); the Sigma log-based rules for the same CVE are Hunting-tier: the structured webserver/proxy logsource fields available to Sigma cannot see the raw Authorization header content, so each Sigma rule matches a broader proxy signal (a URI path, a query parameter, a redirect target) requiring analyst triage rather than automated alerting.


YARA Rules

Detection Rules

CVE-2026-41940 cPanel Harvester Toolkit: Bespoke Component Filenames

Tier: Detection Robustness: 2 ATT&CK Coverage: T1587.001 (Develop Capabilities: Malware), T1588.005 (Obtain Capabilities: Exploits) Confidence: HIGH Rationale: Corrected from the original: the hash-match branch declared each SHA256 value as a strings: literal and matched it as ASCII text content — checking whether the hexadecimal text of the hash appears inside the scanned file, a fundamentally different condition from matching a file whose computed hash equals that value. It could not have fired against the toolkit files it was written to detect and has been removed rather than repaired — a rule whose detection is purely a file hash belongs in the campaign IOC feed, and all eight hashes are already exact-match entries there. The surviving filename-combination branch requires 2 of 7 bespoke, operator-coined names together with a size ceiling, which an operator cannot evade without renaming multiple sibling components across the toolkit. False Positives: None known — all seven strings are bespoke names coined by this operator (e.g. pipeline-41940, whm-hunter, beast-dashboard); requiring 2-of-7 together makes an incidental single-name collision insufficient to fire. Blind Spots: A rebuild that renames every dropped/referenced component evades; the rule matches file content (script self-references, directory listings, orchestrator source) — it does not compute or match file hashes, and misses a fully memory-resident deployment that never touches disk under these names. Validation: Scan the operator’s orchestrator script pipeline-41940.sh (which references sibling toolkit filenames in its own source) or a directory-listing/log capture containing 2+ of the bespoke names — must match; an unrelated file mentioning at most one of these strings incidentally must NOT fire. Deployment: Linux forensic triage, disk-image scanning, incident-response tooling on acquired cPanel/WHM host images, and open-directory/index-page content scanning. Not suitable for real-time victim-endpoint scanning — the toolkit runs on operator-controlled infrastructure, not victim endpoints.

/*
   Yara Rule Set
   Identifier: cPanel Harvester Toolkit — CVE-2026-41940 Operator Files
   Author: The Hunters Ledger
   Source: https://the-hunters-ledger.com/
   License: CC BY 4.0 - https://creativecommons.org/licenses/by/4.0/
*/

rule TOOLKIT_CpanelHarvester41940_KnownFiles {
   meta:
      description = "Detects the operator-built cPanel/WHM credential-harvester toolkit (CVE-2026-41940 exploitation cluster, 216.126.227.49) via a required combination of two or more bespoke, operator-coined component filenames referenced in the toolkit's own orchestrator source or captured in directory-listing/log content. File-hash matching for the eight highest-value toolkit files is carried in the campaign IOC feed, not this rule"
      license = "CC BY 4.0 - https://creativecommons.org/licenses/by/4.0/"
      author = "The Hunters Ledger"
      reference = "https://the-hunters-ledger.com/hunting-detections/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517-detections/"
      date = "2026-05-17"
      hash1 = "4b054892b4a5d7811f57562552d1ea0e8ea5bfbf705ceb71e91126482b650a47"
      family = "cPanel-Harvester-Toolkit-CVE-2026-41940"
      malware_type = "Credential Harvester / Exploitation Toolkit"
      campaign = "OpenDirectory-CVE-2026-41940-cPanel-Harvester-216.126.227.49"
      id = "f0965e55-2c67-5830-bed9-0d228e6cff14"
   strings:
      $fn_pipeline    = "pipeline-41940" ascii wide
      $fn_live_dash   = "live-dashboard-v10" ascii wide
      $fn_whm_hunter  = "whm-hunter" ascii wide
      $fn_beast_dash  = "beast-dashboard" ascii wide
      $fn_beast_page  = "gen-beast-page" ascii wide
      $fn_megahunt    = "megahunt-fast" ascii wide
      $fn_toolkit_dir = "cpanel-toolkit-export" ascii wide
   condition:
      filesize < 50KB and
      2 of ($fn_pipeline, $fn_live_dash, $fn_whm_hunter, $fn_beast_dash,
            $fn_beast_page, $fn_megahunt, $fn_toolkit_dir)
}

Sigma Rules

Hunting Rules

CVE-2026-41940 cPanel WHM Proxy-Subdomain Admin Path Request

Tier: Hunting Robustness: 2 ATT&CK Coverage: T1190 (Exploit Public-Facing Application), T1212 (Exploitation for Credential Access) Confidence: MODERATE Rationale: Anchors on the fixed cPanel/WHM proxy-subdomain admin paths that the CVE targets — a durable, product-level surface, not an operator-rotatable literal. However, the structured webserver logsource fields available here cannot see the raw Authorization header content where the actual null-byte/CRLF injection occurs, so this rule matches any request to the path regardless of payload. Retagged from the original attack.t1556.007/attack.defense-impairment/attack.persistence tags (none of which fit this behavior) to the technique pair actually named in the rule’s own rationale, and demoted from level: high — a bare path hit is not itself confirmed exploitation. False Positives: Legitimate administrator or monitoring traffic to the WHM/cPanel proxy-subdomain admin interface on hosts where the feature is enabled and internet-reachable; authorized security assessment tools (Burp Suite, Nuclei, Metasploit) running assessments against cPanel infrastructure; security researchers probing CVE-2026-41940 in controlled environments. Deployment: Reverse proxy logs (nginx/Apache/HAProxy) in front of cPanel/WHM; WAF alert logs; any HTTP-aware log pipeline ingesting access logs from port 443/2083/2087.

title: CVE-2026-41940 cPanel WHM Proxy-Subdomain Admin Path Request
id: 7f3a2c91-e8d4-4b5a-9c1f-3e6d7a2b0f84
status: experimental
description: >-
  Detects reconnaissance or exploitation attempts against the CVE-2026-41940 proxy-subdomain
  admin paths, a CVSS 9.8 pre-authentication CRLF injection vulnerability in cPanel and WHM
  (disclosed 2026-04-28). The operator toolkit file pipeline-41940.sh at 216.126.227.49
  directly encodes this CVE. Raw Authorization header content, where the actual null-byte or
  CRLF injection occurs, is not exposed as a standard webserver logsource field, so this rule
  anchors on the fixed cPanel/WHM proxy-subdomain path markers the exploit chain targets
  instead — it flags any request to these paths for analyst triage, not a confirmed injection.
references:
    - https://the-hunters-ledger.com/reports/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517/
    - https://nvd.nist.gov/vuln/detail/CVE-2026-41940
author: The Hunters Ledger
date: 2026-05-17
tags:
    - attack.initial-access
    - attack.t1190
    - attack.credential-access
    - attack.t1212
    - detection.emerging-threats
logsource:
    category: webserver
detection:
    selection_auth_null:
        cs-uri-stem|contains:
            - '/___proxy_subdomain_whm'
            - '/___proxy_subdomain_cpanel'
    condition: selection_auth_null
falsepositives:
    - >-
      Legitimate administrator or monitoring traffic to the WHM/cPanel proxy-subdomain
      admin interface on hosts where the feature is enabled and internet-reachable
    - Authorized security assessment tools (Burp Suite, Nuclei, Metasploit) running assessments against cPanel infrastructure
    - Security researchers probing CVE-2026-41940 in controlled environments
level: medium

CVE-2026-41940 Expired Session Marker in Query String

Tier: Hunting Robustness: 2 ATT&CK Coverage: T1190 (Exploit Public-Facing Application), T1212 (Exploitation for Credential Access) Confidence: MODERATE Rationale: expired=1 is the PoC-exact token injected into the Authorization header’s credential portion, per public PoC documentation — a vulnerability-mechanic marker, not an operator choice. But the rule can only observe this marker if it surfaces in the URI query string (the raw header itself is not visible to this logsource, and no log profile that moves it there was observed, so CVE-2026-41940 coverage is NOT CHECKED), and expired=1 is also a generic session-timeout query parameter used by unrelated web applications, so precision is weaker than the original LOW false-positive-risk label claimed. Retagged and demoted from level: medium risk framing to an explicit Hunting posture (level unchanged at medium, which was already appropriately humble). False Positives: Unrelated web applications using expired=1 as a generic session-timeout query parameter; authorized security scanning tools probing cPanel installations. Deployment: Reverse proxy or web access logs that expose the query string (cs-uri-query). The rule reads that one field and nothing from the Authorization header.

title: CVE-2026-41940 Expired Session Marker in Query String
id: a4c8e17b-3f92-4d6e-b08a-5c2d9e4f1a73
status: experimental
description: >-
  Detects the string 'expired=1' in a request URI query string (the rule has no cPanel or WHM host
  test). The same token is the CVE-2026-41940 PoC-exact value that the public PoC documentation
  places in the Authorization: Basic header credential portion to trigger the CRLF auth bypass.
  Raw Authorization header content is not a standard webserver logsource field and the rule tests
  only cs-uri-query; no logging profile that carries the marker from the header into the query
  string was observed, so whether this rule sees CVE-2026-41940 exploitation at all is NOT CHECKED.
  'expired=1' is also a generic session-timeout query parameter used by unrelated web
  applications, so treat matches as a triage lead rather than a confirmed hit.
references:
    - https://the-hunters-ledger.com/reports/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517/
    - https://nvd.nist.gov/vuln/detail/CVE-2026-41940
author: The Hunters Ledger
date: 2026-05-17
tags:
    - attack.initial-access
    - attack.t1190
    - attack.credential-access
    - attack.t1212
    - detection.emerging-threats
logsource:
    category: webserver
detection:
    selection_expired_token:
        cs-uri-query|contains: 'expired=1'
    condition: selection_expired_token
falsepositives:
    - Unrelated web applications using 'expired=1' as a generic session-timeout query parameter
    - Authorized security scanning tools probing cPanel installations
level: medium

CVE-2026-41940 cPanel WHM Proxy-Subdomain Admin Path Request With HTTP 200 Response

Tier: Hunting Robustness: 2 ATT&CK Coverage: T1190 (Exploit Public-Facing Application), T1212 (Exploitation for Credential Access) Confidence: LOW Rationale: Narrows the proxy-subdomain path hit to successful (HTTP 200) responses only, which is a real refinement over the bare path-access rule above, but it still cannot isolate the actual server-side confirmation string (msg_code:[expired_session]) without response-body visibility. The original rule already self-assessed level: low for this reason — that humility is preserved, and the rule is now explicitly filed as Hunting rather than an unlabeled standalone signal. False Positives: Any successful request to the proxy-subdomain path markers — this rule cannot isolate the response-body confirmation string without response-body visibility; treat matches as candidates for manual or WAF-layer confirmation, not standalone high-confidence alerts. Deployment: Web server or reverse proxy access logs that carry the request path (cs-uri-stem) and the response status (sc-status), for example the cPanel/WHM access log or a front-end proxy access log. The rule reads no response body: the msg_code:[expired_session] confirmation needs a separate response-body check at a WAF or inspecting proxy, which this rule does not perform.

title: CVE-2026-41940 cPanel WHM Proxy-Subdomain Admin Path Request With HTTP 200 Response
id: 2e8b5d9f-71a3-4c8e-a25b-6f0d3c7e9b12
status: experimental
description: >-
  Detects HTTP 200 responses to the CVE-2026-41940 proxy-subdomain admin path markers, used
  as a coarse proxy for the server-side confirmation string 'msg_code:[expired_session]' that
  cPanel/WHM returns in the response body after a successful CRLF auth bypass. Standard
  webserver logsource fields do not expose raw response-body content, so the exact
  confirmation string cannot be matched here — deploy a response-body string match at the
  application or WAF layer for high-confidence exploitation confirmation, and use this rule
  only to narrow the candidate set for that manual or WAF-layer review.
references:
    - https://the-hunters-ledger.com/reports/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517/
    - https://nvd.nist.gov/vuln/detail/CVE-2026-41940
author: The Hunters Ledger
date: 2026-05-17
tags:
    - attack.initial-access
    - attack.t1190
    - attack.credential-access
    - attack.t1212
    - detection.emerging-threats
logsource:
    category: webserver
detection:
    selection_auth_bypass_path:
        cs-uri-stem|contains:
            - '/___proxy_subdomain_whm'
            - '/___proxy_subdomain_cpanel'
    selection_success_status:
        sc-status: 200
    condition: selection_auth_bypass_path and selection_success_status
falsepositives:
    - >-
      Any successful request to the proxy-subdomain path markers — this rule cannot isolate
      the response-body confirmation string without response-body visibility; treat matches
      as candidates for manual or WAF-layer confirmation, not standalone high-confidence alerts
level: low

Operator Flask C2 Dashboard Request URI Containing /login-2fa

Tier: Hunting Robustness: 2 ATT&CK Coverage: T1071.001 (Web Protocols) Confidence: MODERATE Rationale: The operator’s C2 dashboard presents a distinctive Werkzeug/3.1.8 banner with a 302 redirect to /login-2fa, but proxy logsource fields expose the client-request path, not response headers — so this rule matches any client request whose URI contains /login-2fa (a substring, so /login-2fa-setup also matches), without host scoping. That is intentional: the rule is designed for peer-C2 discovery across a monitored proxy segment (finding other hosts using the same operator deployment template), not as a host-specific alert, which is why it stays Hunting rather than Detection. False Positives: Legitimate Flask developers running a login route named /login-2fa on a monitored proxy segment (uncommon; verify destination host against confirmed operator infrastructure); security researchers replicating the operator’s C2 in a lab environment. Deployment: Proxy or web access logs that carry the requested URI (c-uri). The report’s Werkzeug-banner and 302-redirect discovery query is a separate out-of-band technique that reads response headers; this rule reads none of that.

title: Operator Flask C2 Dashboard Request URI Containing /login-2fa
id: 5c7d1e4a-9b83-4f2c-8e67-1a3f5c8d2b90
status: experimental
description: >-
  Detects requests whose URI contains the text /login-2fa (a substring test, not an exact path), the redirect target of the Flask C2 dashboard
  operated by the CVE-2026-41940 cPanel harvester cluster (216.126.227.49). The server
  presents HTTP Server: Werkzeug/3.1.8 Python/3.13.12 with a 302 redirect to /login-2fa on
  the initial unauthenticated request; the Werkzeug development server on an internet-facing
  port combined with this custom path fingerprints the operator's deployment pattern.
  Standard proxy logsource fields do not expose response headers (Server banner, Location
  redirect target), so this rule matches the client-request path itself, without host
  scoping — it is intended for peer-C2 discovery across a monitored proxy segment, not as a
  host-specific alert; retain the Shodan/Censys Werkzeug-banner pivot as a complementary
  out-of-band OSINT hunting technique.
references:
    - https://the-hunters-ledger.com/reports/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517/
author: The Hunters Ledger
date: 2026-05-17
tags:
    - attack.command-and-control
    - attack.t1071.001
    - detection.emerging-threats
logsource:
    category: proxy
detection:
    selection_login2fa_path:
        c-uri|contains: '/login-2fa'
    condition: selection_login2fa_path
falsepositives:
    - >-
      Legitimate Flask developers running a login route named /login-2fa on a monitored
      proxy segment (uncommon; verify destination host against confirmed operator infrastructure)
    - Security researchers replicating the operator's C2 in a lab environment
level: medium

Operator Parklogic TDS Landing URL Shape

Tier: Hunting Robustness: 2 ATT&CK Coverage: T1583.008 (Acquire Infrastructure: Malvertising) Confidence: HIGH Rationale: Requires two parameters in the query string, each delimited by a query separator: a=2143526812 as a whole parameter value (so a=21435268120 and xa=2143526812 do not match) and an s= parameter whose value is exactly 64 lowercase hex characters (so a 65th hex character, or any other character after the 64th, does not match). The parameters may appear in either order and with other parameters between them; d= and the leading /? are not required. That is meaningfully more specific than a bare account-ID match. The account ID is still the sole discriminator that ties this shape to this operator rather than any other Parklogic customer (removing it leaves a generic Parklogic platform URL shape), so durability caps below Detection, but the two-part combination has real triage value. Retagged from attack.t1608.005 to attack.t1583.008, matching the malware-analyst’s own campaign-wide MITRE mapping for this Parklogic TDS layer. Regex note: both tests are whole-field regexes written without ^ or $, because Elastic’s regex engine has no anchors and would read them as literal characters; the parameter boundaries are explicit instead ([?&] or the start of the field before the name, & or the end of the field after the value, with & escaped because it is an operator in Elastic’s regex syntax). A backend that searches inside the string rather than matching the whole field does not enforce those boundaries. If the query repeats s=, one value of exactly 64 hex characters is enough; a longer duplicate does not cancel it. False Positives: Other Parklogic customers using the same platform with different a= values (filtered by the a=2143526812 requirement); security researchers reproducing the operator’s TDS chain in testing environments. Deployment: Web proxy URL logs; email gateway URL pattern scanning.

title: Operator TDS Landing URL Pattern - Parklogic Source-Referer Shape with Campaign Hash
id: 3d6c9a7e-2f41-4b8d-c53e-9a1b7f3e5d28
status: experimental
description: >-
  Detects the URL pattern used by the CVE-2026-41940 cPanel harvester operator's Parklogic
  TDS traffic distribution system. The observed shape is /?d=<source-domain>&a=2143526812&s=<64-hex>
  where d= is the source/referrer domain, a= is the operator's Parklogic affiliate account
  ID (constant: 2143526812), and s= is a per-source-domain campaign hash (64 hex characters).
  The rule tests only the a= and s= parameters, each as a whole parameter, in any order; d= and
  the leading /? are not required.
  This shape routes victims from compromised or spoof landing pages through to phishing
  destinations. The account ID is the sole discriminator that ties this shape to this specific
  operator rather than any other Parklogic customer; without it the /?d=&s=<64-hex> shape
  alone is generic Parklogic platform traffic.
references:
    - https://the-hunters-ledger.com/reports/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517/
author: The Hunters Ledger
date: 2026-05-17
tags:
    - attack.resource-development
    - attack.t1583.008
    - detection.emerging-threats
logsource:
    category: proxy
detection:
    selection_account:
        c-uri-query|re: '(.*[?\&])?a=2143526812(\&.*)?'
    selection_s_param:
        c-uri-query|re: '(.*[?\&])?s=[a-f0-9]{64}(\&.*)?'
    condition: selection_account and selection_s_param
falsepositives:
    - Other Parklogic customers using the same platform with different a= values (filtered by the a=2143526812 requirement)
    - Security researchers reproducing the operator's TDS chain in testing environments
level: medium

SSH Authorized Keys File Written Under Root or Home Directories by a Process Outside the OpenSSH Tools

Tier: Hunting Robustness: 2 ATT&CK Coverage: T1098.004 (Account Manipulation: SSH Authorized Keys — dual-tactic: Persistence and Privilege Escalation) Confidence: MODERATE Rationale: SSH authorized_keys modification is a durable, well-known Linux persistence primitive — not specific to this operator, and not directly observed in the recovered toolkit source (inferred from standard post-WHM-root tradecraft, per the original rule’s own MODERATE confidence label). Demoted from level: high: legitimate administration and automation tooling (Ansible, Puppet, Chef, ssh-copy-id, CI/CD key rotation) produce the identical event, so this needs analyst correlation with a prior CVE-2026-41940 exploitation attempt on the same host rather than standing alone. False Positives: Legitimate administrator key management via ssh-copy-id or direct authorized_keys editing (use change-management correlation to exclude); automated configuration management tools (Ansible, Puppet, Chef) managing SSH keys; CI/CD pipeline deployment keys being rotated. Deployment: Linux file integrity monitoring (AIDE, Auditd, Wazuh); EDR file-event logs on cPanel/WHM hosts; Sigma-compatible SIEM with file event indexing. The writer exclusion tests Image, so the feed has to carry the writing process with the file path: raw auditd PATH records carry the path but not the executable, and need joining with the SYSCALL record for the same event.

FP remediation, 2026-08-13. The selector was an endswith on /.ssh/authorized_keys, which looks specific but places no constraint on what precedes it. A full-tree mirror of a compromised host’s home directory still ends in that path, so the rule fired on inert copies pulled into a collection tree. The existing filter_admin_tools exclusion did not help, because it narrows by which process wrote the file (sshd, ssh-copy-id) and the writers here were wget, cp and python3.12. The exclusion was on the wrong axis.

The selector is pinned with startswith, endswith and a whole-field regex written without ^ or $ (Elastic’s regex engine has no anchors and would read them as literal characters). It is anchored to the operative path, /root/.ssh/authorized_keys or /home[0-9]*/<user>/.ssh/authorized_keys. The home segment allows a numeric suffix because cPanel and WHM provision additional home partitions (/home2, /home3) once the primary fills, and a flat /home/ anchor would silently blind the rule on any box built that way. Measured over 45 days on the rule’s own source index: 4 matching events before, 0 after. The process exclusion is kept as an orthogonal layer.

This is high-value coverage and the anchor was chosen not to weaken it. Post-CVE-2026-41940 key planting is exactly the persistence an operator needs once the original bypass is patched, and a key written anywhere SSH will not read accomplishes nothing for them, so the operative-path requirement costs no realistic attacker capability. One unconfirmed gap is recorded rather than assumed away: cPanel’s jailed-shell accounts can place a user’s real authorized_keys outside the flat /home/<user>/.ssh/ shape, and whether the 216.126.227.49 targets used jailshell is unknown. Treat that as LOW-confidence exposure pending evidence.

title: SSH Authorized Keys File Written Under Root or Home Directories by a Process Outside the OpenSSH Tools
id: 6a4f8e2b-1c95-4d7a-f38d-2e9b0c6a5f17
status: experimental
description: >-
  Detects a file event for an SSH authorized_keys file under /root or a /home (or /home2 and
  similar) user directory, written by a process that is not sshd or ssh-copy-id. Nothing in the
  rule tests for a cPanel/WHM host or for CVE-2026-41940. Key planting is documented
  post-exploitation persistence tradecraft after a CVE-2026-41940 CRLF auth bypass, but it is a
  generic Linux persistence primitive inferred from standard post-WHM-root tradecraft, not
  directly observed in the operator's recovered toolkit source, and it is most actionable when
  correlated with a prior CVE-2026-41940 exploitation attempt in web access logs for the same
  host.
references:
    - https://the-hunters-ledger.com/reports/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517/
    - https://nvd.nist.gov/vuln/detail/CVE-2026-41940
author: The Hunters Ledger
date: 2026-05-17
tags:
    - attack.persistence
    - attack.privilege-escalation
    - attack.t1098.004
    - detection.emerging-threats
logsource:
    category: file_event
    product: linux
detection:
    selection_ssh_keys:
        TargetFilename|startswith:
            - '/root/'
            - '/home'
        TargetFilename|endswith: '/.ssh/authorized_keys'
        TargetFilename|re: '(/root|/home[0-9]*/[^/]+)/\.ssh/authorized_keys'
    filter_admin_tools:  # sourced: the OpenSSH server and ssh-copy-id are the standard writers of this file (platform defaults)
        Image|contains:
            - '/usr/sbin/sshd'
            - '/usr/bin/ssh-copy-id'
    condition: selection_ssh_keys and not filter_admin_tools
falsepositives:
    - >-
      Legitimate administrator key management via ssh-copy-id or direct authorized_keys
      editing (use change-management correlation to exclude)
    - Automated configuration management tools (Ansible, Puppet, Chef) managing SSH keys
    - CI/CD pipeline deployment keys being rotated
level: medium

Post-Exploitation File Event Under /var/cpanel/users/ From a Process Outside cPanel’s Own Directories

Tier: Hunting Robustness: 2 ATT&CK Coverage: T1136.001 (Create Account: Local Account) ATT&CK Note: A file event under the account directory suggests an account being written; account creation itself is inferred, which is why the mapping is MODERATE and the rule is Hunting. Confidence: MODERATE Rationale: The rule is a file event under /var/cpanel/users/ written by a process whose image path is not under /usr/local/cpanel/ or /usr/local/whm/. It keeps no admin-session state and does not tell a creation from a modification, so it is a lead for a new account being written outside cPanel’s own tooling, not proof that an account was created. New-cPanel-account creation by something other than cPanel’s own tooling is a durable persistence/monetization primitive, but the toolkit link is speculative: gen-cpanel-access.py (6,070 bytes) is inferred, not confirmed, to generate these artifacts — its source was never recovered. Demoted from level: high and retagged with the sub-technique the malware-analyst’s own campaign mapping uses (T1136.001, not the parent T1136); legitimate reseller account provisioning produces the identical event, so this is a triage lead requiring correlation with signup records, not a standalone indicator. Blind Spots: The exclusion is by image path prefix, so any process running from under /usr/local/cpanel/ or /usr/local/whm/ is excluded, including a binary an intruder places there, and a write made by an excluded cPanel process on the intruder’s behalf is not seen (an account created through a bypassed WHM session would be written by cPanel’s own process, which this filter excludes). False Positives: Legitimate new customer account creation by authorized resellers (correlate against reseller activity logs and customer signup records); automated cPanel processes creating internal system accounts; routine cPanel upgrades creating new system user files. Deployment: Linux file-event telemetry that records both the written path and the writing process image (the rule’s file_event logsource, fields TargetFilename and Image). File integrity monitoring and path-watch records often lack the writing process, and this page declares no mapping for them, so they would not carry the Image exclusion.

title: Post-CVE-2026-41940 Exploitation - File Event Under cPanel Users Directory From a Non-cPanel Process
id: 1b7e3f8a-5c4d-4e9b-a17c-8f2b6e4d0c39
status: experimental
description: >-
  Detects a file event (creation or modification) under /var/cpanel/users/ from a process whose
  image path is not under /usr/local/cpanel/ or /usr/local/whm/, a lead for the documented
  post-exploitation persistence and monetization tradecraft following a CVE-2026-41940 CRLF
  auth bypass. The rule keeps no admin-session state and does not separate a new account file
  from an edit to an existing one. The operator toolkit at 216.126.227.49 includes gen-cpanel-access.py (6070
  bytes, hash unavailable) which is inferred — not directly observed — to generate cPanel
  access artifacts post-compromise; treat matches as a triage lead requiring correlation with
  reseller/customer signup records, not a standalone high-confidence indicator.
references:
    - https://the-hunters-ledger.com/reports/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517/
    - https://nvd.nist.gov/vuln/detail/CVE-2026-41940
author: The Hunters Ledger
date: 2026-05-17
tags:
    - attack.persistence
    - attack.t1136.001
    - detection.emerging-threats
logsource:
    category: file_event
    product: linux
detection:
    selection_cpanel_user_create:
        TargetFilename|startswith: '/var/cpanel/users/'
    filter_whm_admin:
        # sourced: /usr/local/cpanel/ is cPanel's documented install root; the /usr/local/whm/ entry was inherited from the earlier draft and is NOT CHECKED against cPanel documentation
        Image|startswith:
            - '/usr/local/cpanel/'
            - '/usr/local/whm/'
    condition: selection_cpanel_user_create and not filter_whm_admin
falsepositives:
    - >-
      Legitimate new customer account creation by authorized resellers (correlate against
      reseller activity logs and customer signup records)
    - Automated cPanel processes creating internal system accounts
    - Routine cPanel upgrades creating new system user files
level: medium

Suricata Signatures

Detection Rules

Null Byte or Encoded CR/LF After the Base64 Run in an Authorization Basic Header (CVE-2026-41940 Candidate)

Tier: Detection Robustness: 3 ATT&CK Coverage: T1212 (Exploitation for Credential Access), T1190 (Exploit Public-Facing Application) Confidence: MODERATE Rationale: Unlike the Sigma rules for this same CVE, which can only see structured webserver logsource fields, Suricata inspects the normalised Authorization header at the network layer. The rule matches a null byte or a URL-encoded CR/LF (%00, %0a, %0d) that follows the Base64 credential run in an Authorization: Basic header. Well-formed Basic-auth credentials are restricted to the Base64 alphabet, so any of these bytes in that position is a malformed credential, which is why benign hits should be near zero. What the rule does not establish is that the public exploit sends its control bytes there: the report describes them inside the Base64-decoded username, which on the wire is Base64 text and would not match. No retained wire capture of the exploit settles the representation, so the rule is a malformed-credential detector and a candidate for the exploit, not a confirmed detector of it. Added a metadata: attribution field (missing from the original) per Suricata authoring standards. The header test now matches Authorization: in any letter case with any spacing, in line with the PCRE, instead of the exact-case single-space form the content gate used before.

Correction (rev 3): revisions 1 and 2 also matched a raw \x0a or \x0d immediately after the credential. In the http_header buffer every header line ends in CRLF, so [A-Za-z0-9+/=]* consumed the base64 and the alternation then matched the header’s own terminator. The rule fired on every well-formed Basic-auth request, not on exploitation. Raw CR/LF cannot be used to detect this injection in a normalised header buffer, because the reassembled buffer is indistinguishable from a legitimate header boundary. The raw alternatives are removed and the base64 run now requires at least one character (+ rather than *); a null byte and the URL-encoded %00/%0a/%0d forms are retained, none of which can occur in base64. False Positives: Authorized assessment tooling (Burp Suite, Nuclei, Metasploit) that sends a deliberately malformed Authorization: Basic header, or a client that URL-encodes control characters into the credential by mistake. Blind Spots: Requires application-layer HTTP visibility (an inline sensor or TAP in front of the cPanel/WHM host) — does not fire when the vulnerable server sits behind a TLS-terminating CDN that reconstructs the Authorization header before forwarding (see Coverage Gaps). Detects the null-byte and URL-encoded CR/LF variants; an attacker injecting a raw, unencoded CR/LF is not detectable in the normalised header buffer, where it is indistinguishable from the ordinary header terminator, so that variant needs raw-stream inspection rather than an http_header match. Validation: Send an Authorization: Basic <base64>%00 (or %0a, %0d, or a literal null byte) request: the rule must fire; a well-formed Basic-auth login attempt must NOT fire. Whether the public CVE-2026-41940 PoC produces that representation is NOT CHECKED: no PoC replay or retained capture was available, and the report places the control bytes inside the Base64-decoded username. Deployment: Inline IDS/IPS with HTTP application-layer parsing in front of cPanel/WHM infrastructure; network TAP on cPanel hosting provider perimeter. The rule header uses http (application-layer keyword) with any destination port — catches the malformed header on standard ports 2083/2087 and non-standard port migrations without requiring a port list.

alert http any any -> any any (msg:"THL DETECT CVE-2026-41940 Candidate cPanel WHM Control Char After Base64 in Authorization Basic"; flow:established,to_server; content:"Authorization|3a|"; nocase; http_header; pcre:"/Authorization:\s*Basic\s+[A-Za-z0-9+\/=]+(?:\x00|%00|%0[aAdD])/Hi"; reference:cve,2026-41940; reference:url,the-hunters-ledger.com/reports/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517/; reference:url,the-hunters-ledger.com/hunting-detections/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517-detections/; classtype:web-application-attack; sid:9100101; rev:5; metadata:author The_Hunters_Ledger, date 2026-05-17;)

Hunting Rules

Operator Flask C2 Dashboard Banner Hunt: Werkzeug/3.1.8 + /login-2fa

Tier: Hunting Robustness: 2 ATT&CK Coverage: T1071.001 (Web Protocols) Confidence: HIGH for the banner match today; durability is limited (see Rationale) Rationale: The exact Werkzeug/Python version-pinned banner combined with the operator’s custom /login-2fa redirect path is highly precise today, but both halves are brittle to routine operational change rather than deliberate evasion — a Werkzeug upgrade, a restart behind gunicorn/nginx, or fronting the dashboard with a reverse proxy would each independently break this signature without the operator doing anything adversarial. Durability governs the tier call over current precision (see Coverage Gaps for the version-decay note and the Shodan/Censys hunting supplement). Added a metadata: attribution field per Suricata authoring standards. False Positives: The combination of this exact Werkzeug version, Python version suffix, and /login-2fa redirect path is unlikely in unrelated legitimate deployments, but any hit should be corroborated against the operator’s known infrastructure before treating it as a confirmed peer-C2 discovery. Deployment: Internet-facing NDR; Zeek http.log streaming to SIEM; Suricata on monitored egress/ingress points; periodic Shodan/Censys banner-match correlation for peer-infrastructure discovery.

alert http any any -> any any (msg:"THL HUNT CVE-2026-41940 Operator Flask C2 Dashboard - Werkzeug/3.1.8 Banner with /login-2fa Redirect"; flow:established,to_client; http.server; content:"Werkzeug/3.1.8 Python/3.13.12"; endswith; nocase; http.header; content:"Location|3a 20|/login-2fa"; nocase; reference:url,the-hunters-ledger.com/reports/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517/; reference:url,the-hunters-ledger.com/hunting-detections/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517-detections/; classtype:trojan-activity; sid:9100102; rev:3; metadata:author The_Hunters_Ledger, date 2026-05-17;)

Coverage Gaps

Atomics routed to the IOC feed. Two rules in the original file (a Sigma rule and a Suricata signature, both titled “Operator Parklogic TDS … Affiliate ID”) keyed solely on the operator’s Parklogic TDS account ID pkAId=2143526812, removing that single hardcoded literal leaves no behavioral signal in either rule, so both are cut as standalone rules. The account ID is preserved in opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517-iocs.json (behavioral_indicators.url_patterns), alongside the related a=2143526812 TDS URL-shape pattern retained as the Hunting-tier “Operator Parklogic TDS Landing URL Shape” Sigma rule above. A third rule (“Operator Phishing Kit Payload-Fetch URL: /f/[12-hex] Path Pattern”) is also cut: its real precision came entirely from a 13-domain allowlist, all of which are already individually BLOCK-listed in the feed’s network_indicators.domains, and the one specific observed URL (https://officebyt.e56sutx.eps-soltec.cloud/f/d6aba322369c) is already present verbatim in network_indicators.urls. The bare /f/<12-hex> path shape has no independent detection value once the domain scoping is removed. It also appears on unrelated CDN and file-download-handler paths generally.

YARA hash-match branch was non-functional, fixed by removal, not repair. The original YARA rule’s hash-match branch declared each SHA256 value as a strings: literal (e.g. $hash_pipeline = "4b0548...b47") and matched it as ASCII text content. That checks whether the hexadecimal text of the hash appears inside the scanned file’s content, a fundamentally different (and essentially never-true) condition from matching a file whose computed hash equals that value. The branch could not have fired against the toolkit files it was written to detect. Rather than repair it with hash.sha256(0, filesize) == "...", the branch was removed outright: per YARA authoring standards, a rule whose detection is purely a file hash belongs in the campaign IOC feed, not a YARA condition, and all eight hashes are already present there as exact-match entries. The surviving rule keeps its filename-combination branch, which is a genuine content signature and is unchanged.

Sigma log-based CVE-2026-41940 rules retiered to Hunting. All three Sigma rules for the CVE (proxy-subdomain path access, expired-session token marker, and successful-response confirmation) were originally published with a False Positive Risk label of LOW and levels ranging medium-to-high, but the structured webserver logsource fields available to Sigma cannot see the raw Authorization header content where the actual null-byte/CRLF injection occurs. Each rule instead matches a broader proxy signal (a fixed cPanel/WHM admin path, a generic-sounding query parameter, a 200-status response to that path) that legitimate administrator traffic, authorized security scanners, or unrelated web applications can also produce. The Suricata signature above, which inspects the raw header bytes directly, remains this campaign’s only Detection-tier rule for the CVE itself.


YARA String-Pattern Detection Against Toolkit Content: NOT POSSIBLE (Source Code Unrecoverable)

Gap: String-based and byte-pattern YARA rules against the operator’s 37-file Python/Bash toolkit’s actual content are impossible for this campaign. The operator’s development HTTP server was active during the open directory crawl but went offline before source code could be persisted, hashes were computed in memory only, with no source code ever written to disk. There is no byte content to pattern-match against.

What would enable rule creation: Recovery of any toolkit file from an incident-response engagement (disk image acquisition from a compromised cPanel/WHM host, network-capture of an operator file-transfer, or a second operator open-directory exposure with persistence) would enable immediate string-based YARA. The hashes exist and are carried as exact-match entries in the IOC feed; content-based rules require the source.

Workaround in this file: The retained YARA rule TOOLKIT_CpanelHarvester41940_KnownFiles matches 2-of-7 distinctive operator filename strings, a forensic supplement for identifying the toolkit via self-references or directory-listing content, not a substitute for content-level signatures against the toolkit’s actual code.


YARA for HTA Payloads on 216.126.224.181: Not Authored (Low-MODERATE Operator Attribution)

Gap: Five commodity-malware hashes from the .181 IP (Urcbadur/Alien InfoStealer via CVE-2017-0199; ADKP HTA dropper) were recovered from VirusTotal. These have significant detection coverage (8–34 of 76 engines). YARA rules are not authored here for two reasons:

  1. The .181 April 2026 activity is LOW-MODERATE operator attribution. The most parsimonious explanation is a different RouterHosting tenant after the primary operator vacated the IP.
  2. The commodity families already have AV signatures with wide coverage; authoring new rules for them provides minimal incremental detection value.

What would enable rule creation: Evidence confirming the same operator controlled .181 during the April 2026 commodity-malware activity (e.g., WHOIS/infrastructure overlap with the operator’s confirmed org-ID locks, or the same machine-id 6e3644a97f844763a34565b865d35310 appearing in a .181 artifact) would justify authoring operator-attribution YARA for these samples.


cPanel/WHM Audit Log Sigma: Platform-Specific, Not Authored

Gap: Several high-value detection patterns target cPanel-native audit logs (/var/cpanel/accounting.log, /var/cpanel/users/ creation events, email-forwarding rule changes). These require a product: cpanel Sigma logsource category that is not a standard SigmaHQ-supported category. Platform-specific Sigma rules cannot be submitted to the SigmaHQ upstream repository without custom logsource backend support.

Rules that would be valuable:

  • New email-forwarding rule created on a cPanel-hosted mailbox (T1114.003, Email Forwarding Rule)
  • /var/cpanel/accounting.log showing account creation outside logged administrator session (T1136.001)
  • New .php or .cgi file in ~/public_html/ outside normal deploy window (T1505.003)

What would enable rule creation: Addition of a cpanel product backend to SigmaHQ (or deployment in a SIEM with a custom log-source mapping for cPanel audit logs).


Suricata for CVE-2026-41940 on Cloudflare-Fronted cPanel (TLS Inspection Gap)

Gap: The operator’s newer phishing domains (eps-soltec.cloud, tesaco.sbs) route through Cloudflare. A network-layer Suricata rule for CVE-2026-41940 exploitation attempts will not fire when the attacker targets a Cloudflare-fronted cPanel endpoint: the TLS terminates at Cloudflare, and the upstream authorization header is re-constructed by Cloudflare before forwarding to the origin cPanel server. Only rules deployed at the cPanel origin server (not the perimeter IDS) will see the raw header content.

Mitigation path: Deploy Suricata (or equivalent) as a local listener on the cPanel/WHM server itself, or use cPanel’s built-in ModSecurity WAF with the relevant OWASP/CVE rule set.


Werkzeug C2 Banner: Version-Specific Decay

Gap: The Suricata rule THL CVE-2026-41940 Operator Flask C2 Dashboard - Werkzeug/3.1.8 Banner (Hunting-tier, see above) will stop matching if the operator updates Werkzeug (e.g., to 3.1.9 or 3.2.x) or promotes the dashboard behind nginx/gunicorn (which would suppress the Werkzeug Server header entirely). The /login-2fa redirect path is more durable but could be renamed in a toolkit update. This decay risk is the reason the rule is tiered Hunting rather than Detection despite its near-zero false-positive rate today.

Hunting supplement: Run a periodic Shodan/Censys query for http.server:"Werkzeug" combined with a 302 redirect to any path containing login-2fa, this gives version-agnostic peer-C2 discovery beyond what the rule catches in live traffic.


beast-notify.py Notification Channel: Unknown

Gap: The operator’s beast-notify.py (3,960 bytes, SHA256 32b9b9a82913dae5e40842f68791cc639fe690603ccc1d85fe1ae2e99b7bf26b) dispatches per-compromise notifications to an operator-controlled channel. The channel type is unknown (Telegram, Discord webhook, email, or custom HTTPS endpoint). Without source code, no network-layer Suricata rule can be written for the notification channel.

What would enable rule creation: Source recovery of beast-notify.py from an IR engagement would reveal the notification endpoint URL, bot token prefix (if Telegram), or webhook URL format (if Discord), enabling a targeted Suricata rule for the exfiltration/notification channel.


Operator Scanning Behavior: Linux-Side Process Detection Not Covered

Gap: The operator runs mass_v[4-8].py, masscan-boost.sh, and similar scanning tools from their own Linux box. No Sigma rules are authored for victim-side or defender-side detection of these scanning tools because:

  1. The scans originate from operator-controlled infrastructure (AS14956 RouterHosting), not from compromised victim hosts.
  2. Defender visibility into the operator’s own process execution requires access to the operator’s system, which is not a normal defender vantage point.

What would enable rule creation: Network-based detection of the scanning behavior is already partially covered by the Suricata C2 and TDS rules. Full coverage would require the operator’s process creation logs, available only via law enforcement or a honeypot that entices the operator to execute on a monitored system.


License

Detection rules are licensed under Creative Commons Attribution 4.0 International (CC BY 4.0).
Free to use, including commercially, with attribution to The Hunters Ledger.

Cite this detection page

Harrison, J. (2026). Detection Rules — CVE-2026-41940 cPanel Harvester Toolkit — 216.126.227.49. The Hunter's Ledger. https://the-hunters-ledger.com/hunting-detections/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517-detections/. Published 17 May 2026.

CC BY 4.0: free to reuse, including commercially, with attribution and a link to this page.
BibTeX
@misc{hunters-ledger-opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517-detections,
  author       = {Harrison, Joseph},
  title        = {Detection Rules — CVE-2026-41940 cPanel Harvester Toolkit — 216.126.227.49},
  howpublished = {The Hunter's Ledger},
  year         = {2026},
  month        = {may},
  url          = {https://the-hunters-ledger.com/hunting-detections/opendirectory-216-126-227-49-cve-2026-41940-cpanel-harvester-20260517-detections/},
  note         = {Published 17 May 2026. Licensed CC BY 4.0.}
}
Support Independent Threat Research

Everything here is researched, written, and published independently, and none of it sits behind a paywall. If it is useful to you or your team, these are here if you want them.