Back to Intelligence

BdThemes Supply Chain Attack: Poisoned JSON Creates Rogue WordPress Admins — Detection and Remediation Guide

SA
Security Arsenal Team
August 11, 2026
13 min read

WordPress site owners running plugins from vendor BdThemes need to treat this as an active incident, not a news headline. Security researchers have confirmed a supply chain compromise targeting BdThemes that was serious enough for the WordPress.org plugins team to temporarily disable downloads of the vendor's plugins while the incident was investigated and contained.

What makes this attack distinctive — and dangerous — is the mechanism. As Wordfence researcher Paolo Tresso noted, zero source code files were modified within the official WordPress.org repository. Instead of tampering with plugin PHP files (the pattern defenders have been trained to hunt for since the classic plugin-repo compromises), the attackers poisoned JSON data delivered through the plugin's legitimate update/communication channel. That poisoned JSON was then processed by the installed plugin and used to silently create rogue administrator accounts on victim WordPress sites.

This is a mature evolution of the CMS supply chain playbook: if you can't touch the code that reviewers and integrity scanners watch, poison the data the code trusts.

Why Defenders Must Act Now

  • Rogue admin accounts are a beachhead, not an end goal. Once an attacker holds administrator access, they can install backdoored plugins, inject skimmers or SEO spam, modify theme files, harvest user databases, and pivot to the underlying hosting environment.
  • Integrity checks on plugin files will NOT catch this. Standard controls like wp plugin verify-checksums compare installed PHP against the repository — and the repository code was clean. Your detection strategy must shift to behavioral indicators: account creation events, anomalous outbound requests, and unexpected administrator sessions.
  • The blast radius is every site with an affected BdThemes plugin installed. BdThemes is a known vendor in the Elementor/widget ecosystem, and their plugins are deployed across a significant installed base of production sites.

Technical Analysis

Affected Products and Platforms

  • Vendor: BdThemes (WordPress plugin developer, known primarily for Elementor addon/widget packs)
  • Platform: Self-hosted WordPress installations with affected BdThemes plugins installed and able to reach the vendor's remote service/update endpoints
  • Repository status: WordPress.org plugins team temporarily disabled downloads of BdThemes plugins as a containment measure

Because downloads were disabled as a precaution, site owners should assume any BdThemes plugin installed before the takedown may have received poisoned data. Sites that installed the plugins but never allowed them to phone home are lower risk, but "lower" is not "zero."

How the Attack Works

Traditional plugin supply chain compromises follow one of two paths: (1) the attacker's code is committed directly to the repository, or (2) the update server is compromised and pushes a malicious package. Both leave a file-level fingerprint that integrity tooling can catch.

This attack takes a third path:

  1. Plugin makes a routine outbound request. Many commercial/freemium WordPress plugins regularly call vendor APIs for license validation, template/widget library content, changelog data, or feature flags — typically returning JSON.
  2. The JSON response is poisoned upstream. Rather than modifying the plugin's code, the attackers compromised or abused the vendor-side infrastructure serving those responses, injecting malicious payloads into the JSON data the plugin legitimately requests.
  3. The plugin processes the untrusted data. The installed plugin — unmodified and checksum-clean — parses the poisoned JSON and performs privileged actions based on it. In this campaign, the end result was the creation of rogue WordPress administrator accounts on victim sites.
  4. Persistence via legitimate credentials. The attackers don't need webshells or modified files to maintain access. A valid admin username and password is persistence that survives plugin updates, file integrity scans, and most malware cleanup routines.

This is a data-integrity attack, not a code-integrity attack. The lesson for defenders: the trust boundary is not just what code runs, but what data that code consumes and acts on.

Exploitation Status

  • Confirmed active exploitation in the wild. Rogue administrator accounts were observed on compromised sites; this is not theoretical.
  • No CVE has been assigned at the time of this writing, and no CISA KEV entry exists yet. Do not wait for a CVE to act — treat any site with BdThemes plugins as potentially compromised until proven otherwise.
  • The WordPress.org takedown indicates the ecosystem maintainers assessed the risk as serious enough to warrant disrupting the vendor's distribution channel.

Detection & Response

The highest-fidelity indicators for this campaign are: (1) administrator accounts that shouldn't exist, (2) unexpected outbound HTTPS requests from the web/PHP process to vendor-controlled domains, and (3) POST requests hitting account-creation endpoints (direct user-new.php usage, admin-ajax.php user-creation actions, or REST API /wp-json/wp/v2/users calls) from unexpected sources.

Sigma Rules

YAML
---
title: WordPress Rogue Administrator Creation via User Endpoints
id: 3f8a1c72-bd47-4e6a-9c21-7d2e5f8a9b01
status: experimental
description: Detects HTTP POST requests to WordPress account-creation endpoints (user-new.php, REST users route, admin-ajax createuser) which may indicate rogue admin creation from a compromised plugin processing poisoned JSON data, as seen in the BdThemes supply chain attack.
references:
  - https://thehackernews.com/2026/08/bdthemes-supply-chain-attack-poisons.html
  - https://attack.mitre.org/techniques/T1136/001/
author: Security Arsenal
date: 2026/08/10
tags:
  - attack.persistence
  - attack.t1136.001
logsource:
  category: webserver
detection:
  selection_uri:
    cs-uri-stem|contains:
      - '/wp-admin/user-new.php'
      - '/wp-json/wp/v2/users'
      - '/wp-admin/admin-ajax.php'
  selection_method:
    cs-method: 'POST'
  selection_ajax_action:
    cs-uri-query|contains:
      - 'action=createuser'
      - 'action=add-user'
  condition: selection_method and selection_uri and (selection_ajax_action or not cs-uri-stem|contains: '/wp-admin/admin-ajax.php')
falsepositives:
  - Legitimate administrator user provisioning
  - Membership/e-commerce plugins creating customer accounts via admin-ajax
level: high
---
title: WordPress Admin Account Created via WP-CLI or Shell on Web Server
id: 9c2e7b14-5a83-4d9f-b6e2-1a4c8d3f7e56
status: experimental
description: Detects execution of wp-cli user creation commands or direct PHP execution by the web server user, consistent with post-compromise rogue admin creation following the BdThemes supply chain JSON poisoning attack.
references:
  - https://thehackernews.com/2026/08/bdthemes-supply-chain-attack-poisons.html
  - https://attack.mitre.org/techniques/T1136/001/
author: Security Arsenal
date: 2026/08/10
tags:
  - attack.persistence
  - attack.t1136.001
  - attack.execution
logsource:
  category: process_creation
  product: linux
detection:
  selection_wpcli:
    CommandLine|contains:
      - 'wp user create'
      - 'wp_user_create'
  selection_role:
    CommandLine|contains:
      - 'administrator'
      - '--role=admin'
  condition: all of selection_*
falsepositives:
  - Legitimate site provisioning by hosting automation
  - Developer/admin use of WP-CLI for user management
level: high
---
title: Web Server Process Spawning Shell — Possible Post-Exploitation Activity
id: 5d1f9e38-7c64-4b2a-a8f3-6e9b2d4c1a78
status: experimental
description: Detects the web server or PHP-FPM process spawning interactive shells or command interpreters. On a compromised WordPress host, rogue admin access is frequently leveraged to execute system commands via uploaded plugins or theme editors.
references:
  - https://thehackernews.com/2026/08/bdthemes-supply-chain-attack-poisons.html
  - https://attack.mitre.org/techniques/T1059/004/
author: Security Arsenal
date: 2026/08/10
tags:
  - attack.execution
  - attack.t1059.004
logsource:
  category: process_creation
  product: linux
detection:
  selection_parent:
    ParentImage|contains:
      - 'php-fpm'
      - 'apache2'
      - 'httpd'
      - 'nginx'
      - 'litespeed'
  selection_child:
    Image|endswith:
      - '/bash'
      - '/sh'
      - '/dash'
      - '/curl'
      - '/wget'
      - '/nc'
      - '/ncat'
  condition: all of selection_*
falsepositives:
  - Backup or monitoring scripts invoked by the web stack
  - Certain caching/image-processing plugins executing system binaries
level: critical

Tuning note: The first rule will fire on legitimate admin provisioning in environments with active user management. Baseline your expected sources (known admin IPs, provisioning automation) and alert on anything outside that baseline. On most production WordPress sites, admin creation is a rare event — rarity is your friend here.

KQL — Microsoft Sentinel / Defender

If your web server access logs (Apache, Nginx, IIS) are ingested into Sentinel via Syslog/CEF or a custom table, hunt for account-creation activity and correlate with process telemetry from the host:

KQL — Microsoft Sentinel / Defender
// Hunt 1: POST requests to WordPress user-creation endpoints (last 14 days)
// Adjust table name to your ingestion: CommonSecurityLog, W3CIISLog, or custom Apache/Nginx log table
CommonSecurityLog
| where TimeGenerated > ago(14d)
| where RequestMethod == "POST"
| where RequestURL has_any ("/wp-admin/user-new.php", "/wp-json/wp/v2/users")
    or (RequestURL has "admin-ajax.php" and RequestURL has_any ("createuser", "add-user"))
| project TimeGenerated, SourceIP, RequestURL, RequestMethod, DeviceName, ApplicationProtocol
| summarize Requests = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceIP, RequestURL
| order by Requests desc
;

// Hunt 2: Process execution on web hosts - wp-cli user creation or shells spawned by web services
// Requires Syslog or MDE (DeviceProcessEvents) coverage on Linux web servers
DeviceProcessEvents
| where TimeGenerated > ago(14d)
| where (ProcessCommandLine has_all ("wp", "user", "create") and ProcessCommandLine has "admin")
    or (InitiatingProcessFileName has_any ("php-fpm", "apache2", "httpd", "nginx", "litespeed")
        and FileName has_any ("bash", "sh", "dash", "curl", "wget", "nc", "ncat", "python", "perl"))
| project TimeGenerated, DeviceName, InitiatingProcessFileName, FileName, ProcessCommandLine, AccountName
| order by TimeGenerated desc
;

// Hunt 3: Outbound connections from web/PHP processes to plugin vendor infrastructure
// Baseline against known-good vendor endpoints; flag first-time-seen destinations
DeviceNetworkEvents
| where TimeGenerated > ago(14d)
| where InitiatingProcessFileName has_any ("php-fpm", "php", "apache2", "httpd")
| where RemotePort in (443, 80)
| summarize Connections = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
    by RemoteUrl, RemoteIP, DeviceName
| where FirstSeen > ago(7d)  // newly observed destinations in the exposure window
| order by FirstSeen asc

Velociraptor VQL — Endpoint Hunt

For DFIR teams with Velociraptor deployed on hosting infrastructure (or on hosts where you can deploy it during IR), this artifact hunts for recently created/modified artifacts consistent with rogue admin activity and injected content:

VQL — Velociraptor
-- BdThemes Supply Chain IR Hunt: WordPress persistence artifacts
-- Targets: recently modified plugin/theme files, new PHP in uploads,
-- and shells spawned by the web stack

-- 1. Recently modified PHP files in wp-content (potential injected payloads)
SELECT FullPath, Size, Mtime, Atime
FROM glob(globs='/var/www/**/wp-content/**/*.php',
          accessor='file')
WHERE Mtime > timestamp(epoch=now() - 1209600)  -- last 14 days
ORDER BY Mtime DESC

-- 2. PHP files in uploads directory (should almost never exist)
SELECT FullPath, Size, Mtime
FROM glob(globs='/var/www/**/wp-content/uploads/**/*.php',
          accessor='file')

-- 3. Shells/commands spawned by web server processes
SELECT Pid, Ppid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE Username =~ 'www-data|apache|nginx|nobody'
  AND Name =~ 'bash|sh|dash|curl|wget|nc|ncat|python|perl'

The uploads-directory check (hunt #2) is one of the highest-signal, lowest-noise artifacts in WordPress IR: legitimate wp-content/uploads/ contains media and documents, not executable PHP. Any hit there warrants immediate triage.

Triage Script — Rogue Admin Audit and File Integrity Sweep

Run this on any WordPress host that had BdThemes plugins installed. It requires WP-CLI and standard Linux utilities. It audits for rogue administrators, verifies plugin integrity against the repository, and flags recent file changes.

Bash / Shell
#!/bin/bash
# BdThemes supply chain triage — run as a user with WP-CLI access to the site
# Usage: bash bdthemes_triage.sh /var/www/html

WP_PATH="${1:-/var/www/html}"
REPORT="/tmp/wp_triage_$(date +%Y%m%d_%H%M%S).txt"

echo "=== WordPress Supply Chain Triage — $(date) ===" | tee "$REPORT"
echo "Target: $WP_PATH" | tee -a "$REPORT"

# 1. Enumerate ALL administrator accounts — review every entry manually
echo -e "\n[1] Administrator accounts (VERIFY EACH ONE IS EXPECTED):" | tee -a "$REPORT"
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered --path="$WP_PATH" --allow-root 2>/dev/null | tee -a "$REPORT"

# 2. Flag admin accounts registered in the last 30 days (likely window of compromise)
echo -e "\n[2] Admins registered in last 30 days:" | tee -a "$REPORT"
CUTOFF=$(date -d '30 days ago' +%Y-%m-%d 2>/dev/null || date -v-30d +%Y-%m-%d)
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered --path="$WP_PATH" --allow-root 2>/dev/null \
  | awk -v cutoff="$CUTOFF" -F'\t' 'NR>1 && $4 >= cutoff {print "  SUSPICIOUS:", $0}' | tee -a "$REPORT"

# 3. Verify plugin file integrity against WordPress.org repository
echo -e "\n[3] Plugin checksum verification (note: clean checksums do NOT rule out JSON poisoning):" | tee -a "$REPORT"
wp plugin verify-checksums --all --path="$WP_PATH" --allow-root 2>&1 | tee -a "$REPORT"

# 4. Core integrity check
echo -e "\n[4] WordPress core integrity:" | tee -a "$REPORT"
wp core verify-checksums --path="$WP_PATH" --allow-root 2>&1 | tee -a "$REPORT"

# 5. Recently modified files in wp-content (last 14 days)
echo -e "\n[5] Files modified in wp-content in last 14 days:" | tee -a "$REPORT"
find "$WP_PATH/wp-content" -type f -mtime -14 2>/dev/null | tee -a "$REPORT"

# 6. PHP files in uploads — almost never legitimate
echo -e "\n[6] PHP files in uploads directory (HIGH SUSPICION):" | tee -a "$REPORT"
find "$WP_PATH/wp-content/uploads" -name '*.php' -type f 2>/dev/null | tee -a "$REPORT"

# 7. Active admin sessions / recently logged-in users if logging exists
echo -e "\n[7] Check wp_usermeta for session tokens (active sessions per user):" | tee -a "$REPORT"
wp db query "SELECT user_id, meta_key FROM wp_usermeta WHERE meta_key='session_tokens'" --path="$WP_PATH" --allow-root 2>/dev/null | tee -a "$REPORT"

echo -e "\n=== Triage complete. Report saved to $REPORT ===" | tee -a "$REPORT"
echo "NEXT STEPS: Investigate every admin from [2], reset ALL admin passwords, rotate salts/keys in wp-config.php, review [5] and [6] for injected payloads."

Remediation

Immediate Actions (Today)

  1. Identify exposure. Inventory every WordPress site in your environment (including staging, marketing microsites, and customer-hosted instances) for BdThemes plugins. Check both active and inactive plugins — deactivated plugins with the code present can still be relevant depending on how the poisoned data was processed.
  2. Audit every administrator account. This is the primary indicator of compromise for this campaign. Any admin account you cannot attribute to a known, intentional provisioning action must be treated as attacker-controlled: delete it, then hunt for what it did while it existed (plugin installations, theme edits, new pages/posts, settings changes).
  3. Reset all administrator credentials and rotate secrets. Even legitimate admin accounts may have had session tokens harvested. Force password resets for all privileged users, invalidate all sessions (rotating the salts/keys in wp-config.php does this globally), and enforce MFA on every administrator account.
  4. Update or remove affected BdThemes plugins. Apply the cleaned/updated versions from the official WordPress.org repository once the WordPress plugins team re-enables downloads, or remove the plugins entirely until the vendor publishes a verified-clean release with a post-incident statement.

Short-Term Hardening (This Week)

  1. Restrict outbound egress from web servers. WordPress needs to talk to wordpress.org and a small set of vendor/license endpoints — not the internet at large. Egress filtering at the host or perimeter firewall limits the value of poisoned-data channels and slows exfiltration.
  2. Deploy or tighten a WAF. Wordfence, ModSecurity with the OWASP CRS plus WordPress rule sets, or a cloud WAF can alert on anomalous POSTs to user-creation and admin endpoints.
  3. Enable and centralize audit logging. A WordPress activity log plugin (or existing host-level logging) that captures user creation, role changes, plugin/theme modifications, and option changes — shipped off-box to your SIEM — is what turns this class of attack from "invisible for months" into "alerted in minutes."
  4. File integrity monitoring with realistic expectations. FIM on wp-content remains valuable for catching the follow-on payloads attackers drop after gaining admin access, but understand — as this campaign proves — that it cannot catch data-poisoning attacks that leave files untouched.

Strategic Lessons (This Quarter)

  1. Extend supply chain risk assessments to data flows. Your plugin vetting process likely asks "is this code safe?" It must also ask "what remote data does this plugin consume, and what can it do with it?" Any plugin that fetches remote JSON and performs privileged actions based on it is a supply chain surface, even when its code is pristine.
  2. Minimize the plugin footprint. Every installed plugin is a vendor trust relationship. Remove plugins that are not actively maintained or not strictly necessary — the Elementor-addon ecosystem in particular tends to accumulate large, overlapping plugin stacks.
  3. Treat admin creation as a high-severity alertable event. On most production WordPress sites, new administrators are created a handful of times per year. That makes behavioral detection cheap and high-fidelity — wire it into your SOC today.

Reference

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.