wp2shell hits WordPress: detecting pre-auth RCE from plugin drop to command execution
wp2shell is a pre-authentication remote code execution chain in WordPress Core that exploits a route confusion bug in the REST batch endpoint (/wp-json/batch/v1) to achieve SQL injection, escalate to administrator, and upload a plugin-backed webshell. The chain affects WordPress 6.9.0–6.9.4 and 7.0.0–7.0.1 with fixes available in 6.9.5 and 7.0.2 respectively. Elastic Defend detects the exploit through behavioral rules targeting web server processes spawning shells and PHP file creation in plugin directories, with prevention capable of terminating the shell execution at the moment of compromise.
Detection / Hunteropenrouter
What Happened
A serious security flaw in WordPress — the world's most popular website builder — was disclosed on July 17, 2026. The vulnerability, called wp2shell, lets attackers take full control of a WordPress site without needing a password. It works by tricking WordPress's internal request-handling system into running database commands, then using that access to upload malicious code disguised as a plugin. Anyone running WordPress versions 6.9.0 through 7.0.1 is at risk, and attackers are already scanning the internet for vulnerable sites. If you run WordPress, update immediately to version 7.0.2 or 6.9.5. If you cannot patch right away, block public access to the batch API endpoint as a temporary measure. Any internet-facing vulnerable site should be treated as potentially compromised.
Key Takeaways
- wp2shell is a pre-authentication RCE chain in WordPress Core exploiting the REST batch endpoint via route confusion, affecting versions 6.9.0–6.9.4 and 7.0.0–7.0.1; patch to 7.0.2 or 6.9.5 immediately
- The exploit chain uses nested batch requests to bypass method restrictions, achieve SQL injection, then escalate to administrator and upload a plugin-backed webshell — no plugins required on the target
- The durable detection signal is a web server process (apache2, nginx, php-fpm) spawning a shell (dash, bash, sh) to execute commands, not the fragile plugin directory name or User-Agent string
- Elastic Defend with prevention enabled terminates the shell spawn at the Payload Execution by Web Server rule; SIEM rules (PHP File Creation in WordPress Plugin Directory, Suspicious/Unusual Command Execution via Web Server) provide layered detection
- The PoC self-deletes its plugin directory after execution, so a missing wp2shell_* folder does not indicate a clean host if process alerts already fired
Affected Systems
- WordPress 6.9.0 to 6.9.4 (full pre-auth RCE chain)
- WordPress 7.0.0 to 7.0.1 (full pre-auth RCE chain)
- WordPress 6.8.0 to 6.8.5 (SQL injection only, no full RCE chain on this branch)
- Linux hosts running WordPress with Apache (apache2), nginx, or php-fpm as the web server
Vulnerabilities (CVEs)
| CVE | Product | Severity | Description |
|---|---|---|---|
| CVE-2026-63030 | WordPress Core REST batch endpoint | Critical | Route confusion in WordPress batch handling allows sub-requests to be dispatched under wrong REST handlers, enabling pre-auth SQL injection and remote code execution. |
| CVE-2026-60137 | WordPress Core | Critical | Component of the wp2shell pre-auth RCE chain enabling escalation from SQL injection to code execution on default WordPress installs. |
Attack Chain
- Initial Access: Attacker sends nested batch requests to /wp-json/batch/v1 exploiting route confusion to reach pre-auth SQL injection primitive
- Privilege Escalation: SQLi is used to create or elevate a WordPress administrator account via the SQLi-to-administrator bridge
- Staging: Web server (apache2) writes probe files and uploads a zip to wp-content/uploads/, then unpacks PHP into wp-content/upgrade/ and installs to wp-content/plugins/wp2shell_<hex>/
- Execution: Web server process (apache2) spawns a shell (dash) from the plugin working directory to run discovery commands (id, whoami, hostname)
- Discovery: Extended reconnaissance including SUID enumeration (find / -perm -u=s -type f) for privilege escalation opportunities
- Cleanup: PoC self-deletes the plugin directory and staged zip to remove forensic evidence
Detection Availability
- YARA Rules: No
- Sigma Rules: No
- Snort/Suricata Rules: No
- KQL Queries: No
- Splunk SPL Queries: No
- EQL Queries: Yes
- Other Detection Logic: Yes
- Platforms: Elastic Defend behavioral rules, Elastic Detection Rules (SIEM), Elastic Building Block Rules
The article provides EQL query snippets and references multiple Elastic detection rules (TOML format) on GitHub: Payload Execution by Web Server (EDR prevention), PHP File Creation in WordPress Plugin Directory (SIEM), Suspicious/Unusual Command Execution via Web Server (SIEM), and building block rules for file creation and discovery commands. Full rule logic is linked but not reproduced here.
Detection Engineering Assessment
| Dimension | Rating | Rationale |
|---|---|---|
| EDR Visibility | High | Elastic Defend captures file creation events, process lineage (apache2 → dash), working directory metadata, and command-line arguments. Prevention mode terminates shell execution at the Payload Execution by Web Server rule. Process.working_directory set to plugin paths is a key telemetry field. |
| Network Visibility | Medium | Web server access logs capture POST requests to batch endpoints, User-Agent strings, HTTP 207 responses, and follow-on requests to wp-admin endpoints. However, if traffic is encrypted or logs are not centralized, network visibility may be limited. |
| Detection Difficulty | Moderate | The core behavioral signal (web server spawning shell) is reliable and well-documented with pre-built Elastic rules. However, detection requires EDR coverage on web hosts, which is not universal. The INTO OUTFILE variant dropping webshells outside plugin directories requires additional file-monitoring coverage beyond the plugin-scoped rule. |
Required Log Sources
- Linux process execution logs (execve, process.start events)
- Linux file creation/change events in wp-content directories
- Web server access logs (apache2/nginx) with request paths, methods, and User-Agent strings
- Process working directory and parent process metadata
- WordPress application logs if available
Hunting Hypotheses
| Hypothesis | Telemetry | ATT&CK Stage | FP Risk |
|---|---|---|---|
| Consider hunting for any web server process (apache2, nginx, httpd, php-fpm) spawning a shell interpreter (bash, dash, sh) with command-line arguments, as this is the highest-confidence indicator of successful web RCE. | Process execution events with parent process name and child process name/command line | Execution | Low — legitimate web applications rarely spawn interactive shells; scheduled maintenance scripts typically run via cron, not via the web server process directly |
| Consider hunting for PHP file creation events under wp-content/plugins/ or wp-content/cache/ authored by web server processes, as this indicates webshell staging before execution. | File creation events with process.name and file.path | Persistence | Medium — legitimate plugin installations and updates also create PHP files in these directories; correlate with known update windows or admin activity |
| Consider hunting for HTTP POST requests to /wp-json/batch/v1 or /?rest_route=/batch/v1 containing nested JSON requests arrays, especially with non-standard User-Agent strings, as these indicate exploit delivery. | Web server access logs or network proxy logs with full request headers and body | Initial Access | Medium — legitimate WordPress batch API consumers exist; focus on unusual User-Agent strings, high request volume, or requests from unexpected source IPs |
| Consider hunting for web server processes executing discovery commands such as id, whoami, hostname, or find with SUID enumeration flags, as these are common post-exploitation reconnaissance steps. | Process execution events with command-line arguments and parent process context | Discovery | Low to Medium — some monitoring or health-check scripts may run similar commands; verify parent process is a web server rather than a cron job or monitoring agent |
| Consider hunting for self-cleanup scripts that reference wp-content/plugins/ in their command line and delete directories, as the PoC removes its own plugin after execution to destroy evidence. | Process execution events with command-line arguments containing rm and wp-content/plugins path references | Cleanup | Low — legitimate plugin uninstallation typically occurs through wp-admin, not via shell commands from the web server process |
Control Gaps
- The PHP File Creation in WordPress Plugin Directory rule is scoped to wp-content/plugins/ only and will not catch the INTO OUTFILE variant dropping webshells under wp-content/cache/
- Network-only detection (WAF/IDS) may miss the exploit if batch API traffic is encrypted or if the WAF does not inspect JSON request bodies for nested batch structures
- Hosts without EDR coverage will miss the critical web-server-to-shell process lineage signal, which is the most durable detection
- The PoC self-cleanup removes the plugin directory, so file-based hunting alone may produce false negatives if process alerts are not correlated
- Statistical/baseline rules (Unusual Command Execution via Web Server) require a learning period and may not alert on the first exploitation of a newly deployed host
Key Behavioral Indicators
- Process lineage: systemd → apache2 → apache2 → dash → (discovery binary) — web server spawning a shell is the primary RCE signal
- Process.working_directory set to wp-content/plugins/wp2shell_<hex>/ for shell child processes
- Web server process (apache2, nginx, php-fpm) creating PHP files under wp-content/plugins/ or wp-content/cache/
- Shell commands (sh -c) with discovery arguments (id, whoami, hostname) spawned by web server parent
- Self-cleanup command referencing wp-content/plugins/ with rm -rf executed by web server process
- HTTP POST to batch endpoint with User-Agent containing wp2shell, cve-2026-63030, or rezwp2shell
False Positive Assessment
Medium — The core behavioral signal (web server spawning shell) has low false positive risk, but file-creation rules in plugin directories may trigger during legitimate plugin installations or updates. Statistical/baseline rules require a learning period on new hosts. User-Agent and plugin-name IOCs are fragile and will produce false negatives once PoC tooling is modified. Correlating multiple signals (file creation + shell execution + discovery commands from same host within same session) significantly increases confidence.
Recommendations
Immediate Mitigation
- Verify against your organization's incident response runbook and team escalation paths before acting. Patch all internet-facing WordPress instances to 7.0.2 or 6.9.5 immediately; this is the primary and most effective mitigation.
- If patching cannot be completed immediately, consider blocking anonymous access to /wp-json/batch/v1 and /?rest_route=/batch/v1 at the edge (WAF, reverse proxy, or load balancer) as a temporary measure — expect breakage of legitimate batch consumers.
- Consider treating any internet-facing WordPress instance running 6.9.0–6.9.4 or 7.0.0–7.0.1 as potentially compromised; hunt for web server processes spawning shells, unexpected plugin directories, and new administrator accounts.
- If your EDR supports host isolation, consider isolating WordPress hosts showing signs of exploitation (web server spawning shell, wp2shell_* directories) pending forensic review.
Infrastructure Hardening
- Evaluate whether disabling or restricting anonymous REST API access via a WordPress hardening plugin is appropriate for your environment.
- Consider deploying EDR with prevention enabled on all WordPress host infrastructure; the web-server-to-shell behavioral signal is the most durable detection layer.
- If applicable to your architecture, consider running WordPress web servers with read-only filesystem mounts for wp-content/ except during controlled update windows.
- Evaluate whether your WAF or reverse proxy can inspect and block nested batch requests with suspicious patterns at the edge.
User Protection
- Consider enabling and verifying that behavioral detection rules for web server shell execution are active on all WordPress hosts in your environment.
- If using Elastic Defend, consider enabling the pre-built Linux rules listed in the article: PHP File Creation in WordPress Plugin Directory, Suspicious/Unusual Command Execution via Web Server, and Payload Execution by Web Server.
- Consider auditing WordPress administrator accounts for any unexpected creations during the exploitation window.
Security Awareness
- Consider notifying WordPress site administrators in your organization about the critical nature of this vulnerability and the need for immediate patching.
- If your organization manages WordPress instances, consider adding wp2shell to your vulnerability tracking and ensuring patching SLAs are met for Critical-severity CMS vulnerabilities.
- Consider documenting the behavioral detection pattern (web server spawning shell) in your team's detection engineering knowledge base for future web RCE investigations.
MITRE ATT&CK Mapping
Initial Access
Execution
Persistence
Privilege Escalation
Discovery
Additional IOCs
- Urls:
/wp-admin/plugin-install.php- Follow-on request after SQLi-to-admin escalation; indicates plugin upload phase of exploit chain/wp-admin/update.php?action=upload-plugin- Follow-on request for plugin upload action; part of the webshell deployment sequence/wp-json/wp/v2/users?context=edit- Follow-on request to enumerate or manipulate WordPress user accounts after admin escalation
- File Paths:
wp-content/plugins/wp2shell_<hex>/- Plugin directory pattern created by PoC; each shell invocation generates a new directory with random hex suffixwp-content/upgrade/wp2shell_<hex>/- Intermediate unpacking location before plugin is moved to final plugins directorywp-content/cache/- Alternative webshell drop location used by INTO OUTFILE SQLi variant documented by SANS ISC; not covered by plugin-directory-scoped detection ruleswp-content/temp-write-test-*- Write-probe files created by apache2 to confirm wp-content directory is writable before plugin upload stagingwp-content/uploads/wp2shell_<hex>.zip- Staged zip file uploaded during plugin installation phase of the exploit chain
- Command Lines:
- Purpose: Post-exploitation discovery and system identification commands | Tools:
dash,sh| Stage: Execution/Discovery |sh -c -- id - Purpose: SUID binary enumeration for privilege escalation discovery | Tools:
find| Stage: Discovery |find / -perm -u=s -type f - Purpose: Self-cleanup of plugin directory after exploitation to remove forensic evidence | Tools:
sh,rm| Stage: Cleanup |sh -c -- d=$(pwd); case
- Purpose: Post-exploitation discovery and system identification commands | Tools:
- Other:
User-Agent: wp2shell- HTTP User-Agent string used by stock Icex0 PoC on batch API traffic; fragile IOC that disappears if PoC is modifiedUser-Agent: cve-2026-63030/1.0- HTTP User-Agent string from alternative PoC tooling on batch endpoint requestsUser-Agent: rezwp2shell- HTTP User-Agent string from another PoC variant observed on batch trafficHTTP 207 Multi-Status- HTTP response code on batch requests during exploitation; supporting evidence, not standalone indicator