On the heels of fresh threat-intel reporting, CISA has added CVE-2026-119977 to its Known Exploited Vulnerabilities (KEV) catalog — the strongest public signal a defender can receive that a flaw is being weaponized in the wild right now. The vulnerability is a high-severity (CVSS 8.1) Time-of-check Time-of-use (TOCTOU) race condition in WordPress Core that manifests during the software upgrade process and can be leveraged to achieve arbitrary code execution on the underlying web server.
If you operate WordPress — and statistically, a significant percentage of your public-facing web properties probably run it — this is not a "patch when convenient" event. KEV listing means confirmed, observed exploitation. Federal civilian executive branch agencies are now operating under a Binding Operational Directive remediation clock, and every private-sector organization running exposed WordPress instances should treat this with the same urgency. Race conditions in upgrade paths are particularly dangerous because the exploitation window coincides with the exact moment administrators are performing maintenance — often with elevated privileges, relaxed monitoring, and brief gaps in file integrity controls.
This post breaks down how the flaw works, how to hunt for evidence of exploitation in your environment, and how to remediate and harden your WordPress estate.
Technical Analysis
Vulnerability Overview
| Attribute | Detail |
|---|---|
| CVE | CVE-2026-119977 |
| CVSS v3.x Score | 8.1 (High) |
| Vulnerability Class | CWE-367: Time-of-check Time-of-use (TOCTOU) Race Condition |
| Affected Component | WordPress Core — software upgrade / auto-update mechanism |
| Impact | Arbitrary code execution in the context of the web server process |
| Exploitation Status | Actively exploited in the wild; listed in CISA KEV |
| Reference | https://thehackernews.com/2026/11/cisa-confirms-hackers-exploiting.html |
How a TOCTOU Race Condition in the Upgrade Path Works
TOCTOU flaws are a concurrency problem. The WordPress upgrade routine performs a sequence roughly like this: download the update package, verify it (the check), extract it, and then move validated files into place (the use). Between the integrity check and the file installation, there is a window of time where the filesystem state — temporary directories, partially extracted archives, package files — can be manipulated.
An attacker with the ability to influence filesystem state during that window (for example, via a co-resident low-privilege process, a compromised plugin with write access to temp paths, or a crafted request that triggers the update sequence under attacker-controlled timing) can substitute or alter files after validation but before installation. The result: attacker-controlled PHP or executable content lands in the webroot and is treated as legitimate, validated core code. Because WordPress executes PHP under the web server account (commonly www-data, apache, or nginx on Linux hosts), arbitrary code execution follows immediately — and the payload inherits the legitimacy of a "successful" upgrade, which is exactly why defenders may not notice.
Why This Is Operationally Dangerous
- The attack camouflages as administration. Post-exploitation artifacts look like a normal upgrade: new core files, modified timestamps across
wp-includes/andwp-admin/, transient database updates. Alerting tuned to "unusual file changes" often suppresses events during maintenance windows — precisely when this attack fires. - Auto-updates expand the attack surface. Sites configured for automatic background updates trigger this code path without human involvement, meaning an attacker who can influence the timing or trigger an update attempt gets repeated race windows.
- Shared hosting amplifies blast radius. On multi-tenant hosts, code execution as the web server user can expose adjacent sites, configuration files (
wp-config.phpcontains database credentials), and writable upload directories. - RCE as the web user is a beachhead, not the endgame. Expect follow-on activity: web shells dropped into
wp-content/uploads/, credential harvesting fromwp-config.php, and persistence via rogue admin users or mu-plugins.
What to Assume About Post-Exploitation Behavior
Based on typical tradecraft following WordPress core-level code execution, defenders should hunt for:
- Unexpected
.phpfiles inwp-content/uploads/(which should almost never contain executable PHP) - Recently modified files in
wp-includes/orwp-admin/that fail checksum verification against the official release - Web server process (
apache2,nginx,php-fpm) spawning child shells (sh,bash,dash) or system utilities - Newly created administrator accounts or modified
wp-content/mu-plugins/content - Outbound connections from the web server to unfamiliar hosts (C2, payload staging)
Detection & Response
The detections below target the observable behaviors of this exploitation chain: anomalous file writes in WordPress paths during/after the race window, web-server-spawned command execution, and checksum drift against known-good core files. Deploy them in conjunction with your EDR and web log pipeline.
---
title: Web Server Process Spawning Shell or System Utilities
title_note: WordPress post-exploitation behavior
description: Detects web server or PHP-FPM worker processes spawning interactive shells or system utilities, consistent with post-exploitation activity following arbitrary code execution via CVE-2026-119977 on WordPress hosts.
author: Security Arsenal
date: 2026/11/15
status: experimental
references:
- https://thehackernews.com/2026/11/cisa-confirms-hackers-exploiting.html
- https://attack.mitre.org/techniques/T1059/004/
tags:
- attack.execution
- attack.t1059.004
- cve.2026.119977
logsource:
category: process_creation
product: linux
detection:
selection_parent:
ParentImage|endswith:
- '/apache2'
- '/httpd'
- '/nginx'
- '/php-fpm'
- '/php8.1-fpm'
- '/php8.2-fpm'
- '/php8.3-fpm'
selection_child:
Image|endswith:
- '/sh'
- '/bash'
- '/dash'
- '/zsh'
- '/curl'
- '/wget'
- '/nc'
- '/ncat'
- '/python'
- '/python3'
- '/perl'
condition: selection_parent and selection_child
falsepositives:
- Legitimate backup or maintenance scripts invoked by the web application (rare; validate per-environment)
- Health-check plugins executing system commands
level: high
---
title: PHP File Written to WordPress Uploads or Temporary Directories
description: Detects creation of PHP files inside wp-content/uploads or WordPress temporary upgrade directories, consistent with web shell deployment following exploitation of the WordPress Core upgrade race condition (CVE-2026-119977). The uploads directory should not contain executable PHP.
author: Security Arsenal
date: 2026/11/15
status: experimental
references:
- https://thehackernews.com/2026/11/cisa-confirms-hackers-exploiting.html
- https://attack.mitre.org/techniques/T1505/003/
tags:
- attack.persistence
- attack.t1505.003
- cve.2026.119977
logsource:
category: file_event
product: linux
detection:
selection_path:
TargetFilename|contains:
- '/wp-content/uploads/'
- '/wp-content/upgrade/'
- '/wp-content/mu-plugins/'
selection_ext:
TargetFilename|endswith:
- '.php'
- '.phtml'
- '.phar'
- '.php5'
- '.php7'
condition: selection_path and selection_ext
falsepositives:
- Rare plugins that legitimately write PHP to mu-plugins during installation; verify against change records
- mu-plugins writes during sanctioned plugin deployment
level: high
---
title: WordPress Core File Modified Outside Declared Maintenance Window
description: Detects modification of WordPress Core PHP files in wp-includes or wp-admin directories. During CVE-2026-119977 exploitation, attacker-controlled files are installed as part of a poisoned upgrade and will appear as core file modifications. Correlate with change tickets and scheduled update windows.
author: Security Arsenal
date: 2026/11/15
status: experimental
references:
- https://thehackernews.com/2026/11/cisa-confirms-hackers-exploiting.html
- https://attack.mitre.org/techniques/T1565/001/
tags:
- attack.impact
- attack.t1565.001
- cve.2026.119977
logsource:
category: file_event
product: linux
detection:
selection:
TargetFilename|contains:
- '/wp-includes/'
- '/wp-admin/'
TargetFilename|endswith: '.php'
filter_legit_core:
TargetFilename|contains:
- '/wp-admin/includes/update-core.php'
condition: selection and not filter_legit_core
falsepositives:
- Legitimate WordPress upgrades — suppress or alert-low during declared maintenance windows, alert-high otherwise
- Managed hosting provider automated updates
level: medium
// Hunt for web server processes spawning shells/utilities and suspicious file writes
// Ingest Linux auditd/Syslog via CEF or AMA into Sentinel; also covers Defender for Endpoint on Linux.
let webParents = dynamic(["apache2", "httpd", "nginx", "php-fpm", "php8.1-fpm", "php8.2-fpm", "php8.3-fpm"]);
let suspiciousChildren = dynamic(["sh", "bash", "dash", "zsh", "curl", "wget", "nc", "ncat", "python", "python3", "perl"]);
union isfuzzy=true
(Syslog
| where TimeGenerated > ago(7d)
| where Facility =~ "auth" or SyslogMessage has_any ("execve", "syscall")
| where SyslogMessage has_any (webParents) and SyslogMessage has_any (suspiciousChildren)
| project TimeGenerated, Computer, ProcessName, SyslogMessage),
(DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName has_any (webParents)
| where FileName has_any (suspiciousChildren)
| project TimeGenerated, DeviceName, InitiatingProcessFileName, FileName, ProcessCommandLine, InitiatingProcessCommandLine, AccountName),
(CommonSecurityLog
| where TimeGenerated > ago(7d)
| where DeviceVendor =~ "WordPress" or Message has "wp-content/uploads"
| where Message has_any (".php", "update-core", "auto_update")
| project TimeGenerated, SourceIP, DestinationHostName, RequestURL, RequestMethod, Message)
| sort by TimeGenerated desc
-- Artifact: WordPress_PostExploit_Hunt
-- Hunts for executable PHP in uploads, recently modified core files, and web-server-spawned shells.
-- 1) Executable PHP files in wp-content/uploads (web shell indicator)
SELECT FullPath, Mtime, Size
FROM glob(globs='/var/www/**/wp-content/uploads/**/*.php',
accessor='file')
WHERE Mtime > epoch(seconds=now() - 604800)
-- 2) WordPress core files modified in the last 7 days (checksum drift candidates)
SELECT FullPath, Mtime, Size
FROM glob(globs='/var/www/**/wp-includes/*.php',
accessor='file')
WHERE Mtime > epoch(seconds=now() - 604800)
-- 3) Web server processes with suspicious child command lines
SELECT Pid, Name, CommandLine, Exe, Username, CreateTime
FROM pslist()
WHERE CommandLine =~ 'wp-content/uploads.*\.php|/tmp/|/dev/shm/'
OR (Username =~ 'www-data|apache|nginx' AND Name =~ '^(sh|bash|dash|curl|wget|nc|python3?|perl)$')
#!/bin/bash
# CVE-2026-119977 - WordPress Core verification & hardening script
# Run as root (or via sudo) on the WordPress host.
# Requires wp-cli (https://wp-cli.org/) for checksum verification.
set -euo pipefail
WP_ROOTS=("/var/www/html" "/var/www" "/srv/www")
WP_USER="www-data" # adjust: apache / nginx / your web user
echo "[+] Locating WordPress installations..."
for root in "${WP_ROOTS[@]}"; do
[ -d "$root" ] || continue
find "$root" -maxdepth 4 -name wp-config.php 2>/dev/null
done | while read -r cfg; do
site_dir="$(dirname "$cfg")"
echo "[+] Found WordPress at: $site_dir"
# 1) Report installed core version — verify it matches the latest patched release from wordpress.org
sudo -u "$WP_USER" wp core version --path="$site_dir" --allow-root 2>/dev/null || \
echo " [!] wp-cli unavailable; check version in $site_dir/wp-includes/version.php"
# 2) Verify core checksums — ANY mismatch on a patched version is a red flag (possible poisoned upgrade)
echo "[+] Verifying core checksums..."
sudo -u "$WP_USER" wp core verify-checksums --path="$site_dir" --allow-root 2>/dev/null || \
echo " [!] Checksum verification failed or wp-cli missing — investigate manually"
# 3) Find PHP files inside uploads (web shell indicator)
echo "[+] Scanning uploads for executable PHP..."
find "$site_dir/wp-content/uploads" -type f \( -name "*.php" -o -name "*.phtml" -o -name "*.phar" \) \
-mtime -14 -ls 2>/dev/null || true
# 4) Find recently modified core files
echo "[+] Recently modified core files (last 7 days):"
find "$site_dir/wp-includes" "$site_dir/wp-admin" -type f -name "*.php" -mtime -7 -ls 2>/dev/null || true
# 5) Audit administrator accounts for rogue users
echo "[+] Enumerating administrator accounts — validate each is expected:"
sudo -u "$WP_USER" wp user list --role=administrator --fields=user_login,user_email,user_registered \
--path="$site_dir" --allow-root 2>/dev/null || true
done
# 6) Harden uploads directory: deny PHP execution via .htaccess (Apache)
echo "[+] Writing PHP-execution deny rules to uploads directories..."
for root in "${WP_ROOTS[@]}"; do
find "$root" -maxdepth 5 -type d -path "*/wp-content/uploads" 2>/dev/null | while read -r updir; do
ht="$updir/.htaccess"
if [ ! -f "$ht" ]; then
printf '<FilesMatch "\\.(php|phtml|phar|php5|php7)$">\n Require all denied\n</FilesMatch>\n' > "$ht"
chmod 644 "$ht"
echo " [+] Hardened: $ht"
fi
done
done
echo "[+] Done. Remediation: update WordPress Core to the latest patched release immediately."
echo " See: https://wordpress.org/news/ and the CISA KEV entry for CVE-2026-119977."
Remediation
-
Patch immediately. Update WordPress Core to the latest release that resolves CVE-2026-119977. Confirm your running version via
wp core versionorwp-includes/version.phpand compare against the current release at https://wordpress.org/news/category/releases/. Do not rely on auto-update having succeeded — verify checksums after patching withwp core verify-checksums, because exploitation of this flaw produces installations that report as successfully upgraded while containing attacker-modified files. -
Treat the CISA KEV deadline as your deadline. KEV listing carries a mandated remediation date for federal civilian agencies under BOD 22-01; private-sector organizations should adopt the same date as their internal SLA. Check the KEV catalog entry at https://www.cisa.gov/known-exploited-vulnerabilities-catalog for the current due date.
-
Hunt before you assume you're clean. Because the flaw is exploited during the upgrade window itself, a patched site may already be compromised. Run the checksum verification and the file-system hunts above on every WordPress instance, including staging and forgotten subdomains. Any core file mismatch on a fully patched version = incident response trigger.
-
If compromise is suspected: isolate the host, preserve disk and access logs (
/var/log/apache2/,/var/log/nginx/, auth logs) before rebuilding, rotate database credentials inwp-config.phpand all admin/API credentials, audit the administrator user list andmu-plugins/, and rebuild from known-good source rather than cleaning in place. File-timestamp analysis around your last upgrade window is your highest-value forensic starting point. -
Harden the attack surface going forward:
- Deny PHP execution in
wp-content/uploads/at the web server layer (the script above handles Apache; on nginx, add alocationblock returning 403 for\.php$under uploads). - Restrict write access to WordPress temp and upgrade directories to the web server user only; on shared hosting, ensure tenant isolation.
- Disable file modification from the dashboard (
define('DISALLOW_FILE_EDIT', true);) and considerDISALLOW_FILE_MODSwhere your update workflow permits. - Deploy a file-integrity monitoring solution (Wazuh, Tripwire-style, or your EDR's FIM) over the webroot with alerts routed to the SOC — not suppressed during maintenance windows, but correlated against declared change tickets.
- Restrict outbound egress from web servers. A compromised WordPress host that cannot reach the internet cannot stage payloads or establish C2.
- Deny PHP execution in
-
Inventory your exposure. WordPress sprawl is real — marketing microsites, abandoned campaign pages, vendor-hosted blogs. If you cannot enumerate your WordPress estate today, that is the first finding of this engagement.
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.