Back to Intelligence

CVE-2026-78570: Critical Unauthenticated Privilege Escalation in WordPress Total Donations Plugin — Detection and Remediation Guide

SA
Security Arsenal Team
August 25, 2026
10 min read

The National Vulnerability Database has published CVE-2026-78570, a CVSS 9.8 (Critical) vulnerability in the Total Donations plugin for WordPress, affecting all versions up to and including 2.0.5. The flaw is network-exploitable and requires no authentication: a remote attacker can elevate privileges to that of a WordPress administrator with nothing more than HTTP access to the target site.

In fifteen years of incident response, I can tell you that unauthenticated privilege-escalation bugs in WordPress plugins are among the fastest-weaponized vulnerabilities we see. The exploitation pattern is painfully predictable: once an attacker holds an administrator account on a WordPress instance, they install a malicious plugin or theme, drop a webshell into wp-content/uploads, and convert a brochure-ware site into a phishing host, SEO-poisoning node, or initial-access beachhead into your internal network. If your organization — or any of your clients, if you're an MSSP — runs Total Donations, treat this as an emergency change, not a routine patch cycle.

Technical Analysis

Affected Products and Versions

AttributeDetail
CVECVE-2026-78570
CVSS v3.x Score9.8 (Critical)
Attack VectorNetwork (AV:N), low complexity, no privileges, no user interaction
Affected ProductTotal Donations plugin for WordPress
Affected VersionsAll versions ≤ 2.0.5
ImpactUnauthenticated privilege escalation to administrator
Referencehttps://nvd.nist.gov/vuln/detail/CVE-2026-78570

How the Vulnerability Works — Defender's Perspective

Privilege-escalation flaws in WordPress plugins of this class almost universally trace back to one root cause: a plugin-registered AJAX handler or REST endpoint that performs a privileged action without a proper authorization/capability check. WordPress exposes wp-admin/admin-ajax.php to unauthenticated visitors via the wp_ajax_nopriv_{action} hook. When a plugin registers a nopriv handler that updates options, user meta, or roles — and fails to call current_user_can() or verify a nonce — any anonymous remote client can invoke it.

The typical attack chain for CVE-2026-78570-class bugs looks like this:

  1. Reconnaissance — Attacker enumerates /wp-content/plugins/total-donations/ or scrapes the readme/changelog to fingerprint a vulnerable version.
  2. Privilege escalation request — A crafted unauthenticated POST to /wp-admin/admin-ajax.php (or a plugin REST route) invokes the vulnerable handler, which either flips the WordPress default_role option to administrator, enables registration, or directly creates/promotes an account.
  3. Account creation/login — The attacker registers or authenticates with their new administrator account.
  4. Persistence and code execution — With admin access, the attacker uploads a malicious plugin/theme ZIP via the dashboard, edits theme files (Appearance → Theme File Editor), or drops a standalone PHP webshell into a web-accessible directory.
  5. Post-exploitation — Webshell traffic, outbound C2, credential harvesting from wp-config.php (database credentials, salts), and lateral movement into any system trusting the web server.

The exploitation requirement is a single HTTP request from the internet. There is no mitigation in configuration — the vulnerable code path is reachable by default on every exposed site running the plugin.

Exploitation Status

As of publication, CVE-2026-78570 is newly published by NVD. Given the CVSS 9.8 network-exploitable, unauthenticated nature of the flaw and the historically rapid weaponization of WordPress plugin privilege escalations, defenders should assume active scanning and exploitation attempts are imminent or underway. Automated botnets fingerprint WordPress plugin inventories continuously; the window between NVD publication and mass scanning for this vulnerability class is routinely measured in hours, not days. Monitor the NVD entry and CISA KEV catalog for updates, but do not wait for KEV inclusion to act — CVSS 9.8 unauthenticated privilege escalation on a public-facing CMS is self-evidently urgent.

Detection & Response

Detection for this threat has three layers: (1) the exploitation request itself against admin-ajax.php or plugin endpoints, (2) the account-creation/role-change artifacts in WordPress, and (3) post-exploitation behavior — webshells and web server process anomalies. The rules below target each layer.

Sigma Rules

YAML
---
title: Total Donations Plugin Exploitation Attempt via admin-ajax.php
description: Detects unauthenticated POST requests to WordPress admin-ajax.php referencing the Total Donations plugin, consistent with CVE-2026-78570 privilege escalation attempts.
references:
  - https://nvd.nist.gov/vuln/detail/CVE-2026-78570
author: Security Arsenal
date: 2026/02/10
status: experimental
tags:
  - attack.initial_access
  - attack.t1190
logsource:
  category: webserver
  product: apache
  service: access
detection:
  selection_uri:
    cs-uri-stem|endswith: '/wp-admin/admin-ajax.php'
  selection_plugin:
    cs-uri-query|contains:
      - 'total_donations'
      - 'total-donations'
      - 'totaldonations'
  selection_method:
    cs-method: 'POST'
  condition: selection_uri and selection_plugin and selection_method
falsepositives:
  - Legitimate donor interactions with the plugin front-end (review volume and source distribution)
level: high
---
title: PHP File Created in WordPress Uploads Directory
description: Detects creation of PHP files under wp-content/uploads, a common webshell drop location following WordPress administrator compromise via CVE-2026-78570.
references:
  - https://nvd.nist.gov/vuln/detail/CVE-2026-78570
  - https://attack.mitre.org/techniques/T1505/003/
author: Security Arsenal
date: 2026/02/10
status: experimental
tags:
  - attack.persistence
  - attack.t1505.003
logsource:
  category: file_event
  product: linux
detection:
  selection:
    TargetFilename|contains: '/wp-content/uploads/'
    TargetFilename|endswith:
      - '.php'
      - '.phtml'
      - '.php5'
      - '.phar'
  condition: selection
falsepositives:
  - Rare legitimate plugin/theme functionality that writes PHP to uploads (investigate writer process)
level: high
---
title: Web Server Process Spawning Shell or Command Interpreter
description: Detects web server worker processes (apache2, nginx, php-fpm) spawning shells or system utilities, indicating post-exploitation command execution after WordPress compromise.
references:
  - https://attack.mitre.org/techniques/T1059/004/
  - https://nvd.nist.gov/vuln/detail/CVE-2026-78570
author: Security Arsenal
date: 2026/02/10
status: experimental
tags:
  - attack.execution
  - attack.t1059.004
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentImage|endswith:
      - '/apache2'
      - '/nginx'
      - '/php-fpm'
      - '/php-fpm8.1'
      - '/php-fpm8.2'
      - '/php-fpm8.3'
  selection_child:
    Image|endswith:
      - '/sh'
      - '/bash'
      - '/dash'
      - '/zsh'
      - '/curl'
      - '/wget'
      - '/nc'
      - '/ncat'
      - '/python'
      - '/python3'
      - '/perl'
  condition: selection_parent and selection_child
falsepositives:
  - Legitimate WordPress plugins invoking system binaries (e.g., image processing, backups) - tune per environment
level: high

KQL — Microsoft Sentinel / Defender Hunt

This query hunts web logs (IIS, Apache via CEF/Syslog ingestion, or Firewall/WAF logs) for exploitation requests targeting the Total Donations plugin through admin-ajax.php, and correlates with outbound connection anomalies from the web server.

KQL — Microsoft Sentinel / Defender
let Lookback = 14d;
let ExploitRequests = union isfuzzy=true
    (CommonSecurityLog
    | where TimeGenerated > ago(Lookback)
    | where RequestURL has "/wp-admin/admin-ajax.php"
    | where RequestURL has_any ("total_donations", "total-donations", "totaldonations")
    | extend Source = "CommonSecurityLog"),
    (W3CIISLog
    | where TimeGenerated > ago(Lookback)
    | where csUriStem has "admin-ajax.php"
    | where csUriQuery has_any ("total_donations", "total-donations", "totaldonations")
    | extend Source = "W3CIISLog", SourceIP = cIP, RequestURL = strcat(csUriStem, "?", csUriQuery));
ExploitRequests
| summarize FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), RequestCount = count(), DistinctURIs = dcount(RequestURL) by SourceIP, Source
| sort by RequestCount desc
| extend Severity = iff(RequestCount > 20, "Likely automated exploitation", "Investigate");

A second hunt targets the post-exploitation phase — a web server initiating unusual outbound connections after a suspicious request window:

KQL — Microsoft Sentinel / Defender
let Lookback = 14d;
DeviceNetworkEvents
| where TimeGenerated > ago(Lookback)
| where InitiatingProcessName in~ ("apache2", "nginx", "php-fpm", "php", "php-cgi")
| where RemotePort in (80, 443, 8080, 4444, 1337)
| where RemoteIPType == "Public"
| summarize Connections = count(), DistinctRemoteIPs = dcount(RemoteIP), RemoteIPs = make_set(RemoteIP, 20) by DeviceName, InitiatingProcessName, bin(TimeGenerated, 1h)
| where DistinctRemoteIPs > 3 or Connections > 50
| sort by Connections desc;

Velociraptor VQL — Webshell and Artifact Hunt

Deploy this artifact across your Linux web server fleet to find PHP files written into upload directories (webshell staging) and enumerate recent modifications to WordPress core/plugin paths:

VQL — Velociraptor
-- Hunt for PHP webshells in WordPress uploads directories and recently modified plugin files
LET upload_paths = SELECT FullPath, Mtime, Size
FROM glob(globs='/var/www/**/wp-content/uploads/**/*.php', accessor='file')
WHERE Mtime > (now() - 1209600)

LET plugin_changes = SELECT FullPath, Mtime, Size
FROM glob(globs='/var/www/**/wp-content/plugins/**/*.php', accessor='file')
WHERE Mtime > (now() - 604800)
  AND NOT FullPath =~ 'total-donations'

SELECT FullPath, Mtime, Size, 'PHP in uploads directory' AS Finding
FROM upload_paths
UNION ALL
SELECT FullPath, Mtime, Size, 'Recently modified plugin file' AS Finding
FROM plugin_changes
ORDER BY Mtime DESC

Also enumerate live web server processes and their network connections for signs of active C2:

VQL — Velociraptor
-- Correlate web server processes with active outbound network connections
LET webprocs = SELECT Pid, Name, CommandLine, Username
FROM pslist()
WHERE Name =~ 'apache2|nginx|php-fpm|php'

SELECT Pid, Name, CommandLine, Username,
       netstat(Pid=Pid) AS Connections
FROM webprocs

Remediation and Verification Script

Run this on each WordPress host to identify the vulnerable plugin, remove/disable it, and audit for rogue administrator accounts and dropped webshells:

Bash / Shell
#!/bin/bash
# CVE-2026-78570 - Total Donations plugin verification and remediation
# Run as root or with sudo on the WordPress host

WP_PATHS=$(find /var/www /srv/www /home -maxdepth 4 -name "wp-config.php" 2>/dev/null | xargs -I{} dirname {})

echo "=== [1] Checking for Total Donations plugin installs ==="
for WP in $WP_PATHS; do
  PLUGIN_DIR="$WP/wp-content/plugins/total-donations"
  if [ -d "$PLUGIN_DIR" ]; then
    echo "[!] FOUND plugin directory: $PLUGIN_DIR"
    if [ -f "$PLUGIN_DIR/readme.txt" ]; then
      grep -i "Stable tag" "$PLUGIN_DIR/readme.txt"
    fi
    echo "[!] DEACTIVATING and REMOVING vulnerable plugin..."
    mv "$PLUGIN_DIR" "${PLUGIN_DIR}.QUARANTINED_$(date +%Y%m%d)"
  else
    echo "[OK] No Total Donations plugin in $WP"
  fi
done

echo "=== [2] Auditing administrator accounts (requires wp-cli) ==="
for WP in $WP_PATHS; do
  if command -v wp >/dev/null 2>&1; then
    echo "--- $WP ---"
    sudo -u www-data wp user list --role=administrator --fields=user_login,user_email,user_registered --path="$WP" --allow-root 2>/dev/null
  fi
done

echo "=== [3] Checking default_role and registration options ==="
for WP in $WP_PATHS; do
  if command -v wp >/dev/null 2>&1; then
    sudo -u www-data wp option get default_role --path="$WP" --allow-root 2>/dev/null
    sudo -u www-data wp option get users_can_register --path="$WP" --allow-root 2>/dev/null
  fi
done

echo "=== [4] Hunting PHP files in uploads (last 30 days) ==="
find /var/www /srv/www /home -path "*/wp-content/uploads/*" -name "*.php" -mtime -30 2>/dev/null

echo "=== [5] Grepping access logs for exploitation attempts ==="
grep -E "admin-ajax.php.*(total[_-]donations|totaldonations)" /var/log/apache2/access.log* /var/log/nginx/access.log* 2>/dev/null | tail -50

echo "=== Complete. Review flagged accounts, quarantined plugins, and log hits before returning to service. ==="

Remediation

  1. Remove or update the plugin immediately. All versions ≤ 2.0.5 are vulnerable. Check the WordPress plugin repository and the vendor's channel for a patched release greater than 2.0.5; if none exists, deactivate and delete the plugin. There is no reliable configuration workaround — the vulnerable code path is exposed to unauthenticated traffic by design. Do not rely on "hide the version" tactics; they do not close the hole.
  2. If removal is not immediately possible, apply WAF/virtual patching. Block POST requests to /wp-admin/admin-ajax.php carrying action parameters referencing Total Donations handlers, and block access to /wp-content/plugins/total-donations/ at the edge. Treat this as a stopgap measured in hours, not a fix.
  3. Assume compromise and audit. For every site that ran the vulnerable plugin while internet-exposed: enumerate all accounts with administrator role (wp user list --role=administrator) and validate each against known staff; check default_role is subscriber and users_can_register is 0 unless intentionally otherwise; review wp-content/uploads for PHP files; inspect recently modified theme/plugin files and the active theme's functions.php.
  4. Rotate credentials on any suspect site. WordPress salts and keys in wp-config.php, database credentials, and all administrator passwords. If the database was reachable, assume its contents (user hashes, donor PII — note this plugin handles donations, so payment-adjacent data may be in scope for PCI-DSS and breach-notification obligations) are exposed.
  5. Hunt retroactively. Run the Sigma/KQL/VQL content above against at least 14–30 days of retained web logs. Look for the first admin-ajax.php hit from a given source IP and trace everything that IP (and subsequent admin sessions) touched.
  6. Track the advisory. Monitor https://nvd.nist.gov/vuln/detail/CVE-2026-78570 for updated CPE data, patch-version confirmation, and CISA KEV inclusion, and follow your organization's emergency-patching SLA for CVSS 9.8 network-exploitable flaws on internet-facing assets.

Related Resources

Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub

Is your security operations ready?

Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.