What the wp2shell Attack Looked Like in Our Server Logs

wp2shell attack entries in WordPress server logs under a magnifying glass, with a shield showing the requests were blocked

On July 17, the WordPress security team released an emergency patch for a pair of vulnerabilities that, chained together, let an anonymous attacker run code on a WordPress server with no login, no password, and no vulnerable plugin required. A single crafted request against a default installation was enough.

The security community named the exploit chain wp2shell. Within days it was being fired at millions of sites by automated tooling, and both vulnerabilities were added to CISA’s Known Exploited Vulnerabilities catalog.

We watched unsuccessful attempts happen in real time across the sites we maintain. This post covers what it looked like from our side: the traffic, the timeline, and the checks we ran to confirm nothing landed. If you run a WordPress site, the section on checking your own server is the part worth bookmarking.

What wp2shell is

Two separate flaws in WordPress core:

On their own, each is serious. Chained, they produce unauthenticated remote code execution, which is the most severe outcome a web vulnerability can have. It means an attacker who has never touched your site, does not know your username, and has not tricked anyone into clicking anything can execute their own code on your server.

The versions that fix it are 7.0.2, 6.9.5, and 6.8.6. The full chain works against 6.9 and newer, because that is when the batch route flaw was introduced. Version 6.8 is affected by the SQL injection on its own, which is why 6.8.6 exists. Versions before 6.8 are not affected. If your site is on any 6.8, 6.9, or 7.0 release below those three numbers, it needs to be updated.

One number causes confusion, so it is worth stating plainly: 7.0.1 is not patched. If your site reports 7.0.1, it needs to be updated.

The exploit was dangerous because it took no skill to use. Public proof of concept code circulated within a day of disclosure, and from that point an attacker needed nothing but a script and a list of domains.

wp2shell timeline from July 17 patch release to public exploit code, mass exploitation, and CISA KEV listing

What the attack looked like in production

The traffic arrived in two distinct waves.

First, reconnaissance. Automated scanners sending harmless looking GET requests to the batch endpoint, checking which sites responded and building target lists. These came from dozens of IP addresses across Europe, Asia, and North America within roughly 48 hours of disclosure. Nothing about this phase is targeted. It is the internet being swept end to end.

Then, payloads. POST requests carrying actual exploit code. These are the ones that matter. In our logs, many of them arrived with a user agent string that made no attempt to disguise itself:

"POST /?rest_route=/batch/v1" 403 "wp2shell/2.0"

The tool announced itself by name. Four days after the patch, exploitation was already so commoditized that attackers were not bothering to disguise their traffic.

We also saw the attempts escalate. Requests carrying SQL injection payloads aimed at the batch endpoint. Requests probing for webshell filenames, which is an attacker checking whether a site had already been compromised by someone else. Repeated bursts from single addresses hitting the same endpoint several times within a minute.

Every one of those requests, across every site we manage, was rejected. The response codes in our logs for the exploit path after July 17 were 403, 404, 301, and 302. Not one request was processed.

Why HTTP 207 responses are ambiguous

None of the advisories we read covered this, and it matters if you are auditing your own logs.

The WordPress batch endpoint is a legitimate part of core. The block editor uses it. Plenty of integrations and sync tools use it. When it processes a request successfully, it returns HTTP 207, Multi Status.

That creates a real problem for anyone auditing logs, because a successful exploit also produces a 207. The status code alone cannot tell you whether you are looking at your own automation working correctly or an attacker succeeding.

We found more than a thousand 207 responses in our logs during the audit. Sorting them out required two independent checks:

  1. Date. Every one of them predated the July 17 disclosure. Traffic from before the vulnerability was public cannot be wp2shell exploitation.
  2. Source. They traced back to a known integration on a specific site, using a consistent request pattern from a consistent origin.
HTTP 207 comparison for wp2shell log audits: legitimate batch automation signals versus signs that need investigation

Had even one 207 appeared after July 17 from an unrecognized source, that site would have gone straight to a full forensic workup. None did.

If you are auditing your own logs, do not treat 403 and 404 as the only outcomes worth counting. Look at everything, and pay particular attention to anything that succeeded.

How to check your own site

If you manage a WordPress site and you are not certain where you stand, these are the checks. Adjust file paths for your own hosting environment.

Five checks for wp2shell on a WordPress site: core version, log search, checksums, uploads PHP scan, admin audit

1. Confirm your version. This is the single most important check.

wp core version

A pass is 7.0.2, 6.9.5, or 6.8.6. Anything else needs updating immediately.

2. Check whether exploit traffic reached your server.

zgrep -h "batch/v1" /path/to/your/access.log*

Using zgrep rather than grep matters, because it searches compressed rotated logs as well as current ones. The attack window is mid to late July, and on a busy site those entries have long since rotated out of anything a control panel log viewer will show you.

Empty output means nothing touched the exploit endpoint. If you get results, look at the request method and the response code. GET requests returning 404 are harmless probes. POST requests are the ones to examine.

3. Verify your core files have not been altered.

wp core verify-checksums

Silence means clean. Warnings about unknown or modified files in the WordPress directories are a red flag.

4. Look for PHP files where they do not belong.

find wp-content/uploads -name "*.php"

Your uploads directory should contain zero PHP files. Anything this returns deserves scrutiny.

5. Audit your administrator accounts.

wp user list --role=administrator --fields=user_login,user_email,user_registered

Any admin account you did not create, or a changed email address on an account you did, is an incident and not a curiosity.

Patching closes the hole, but it does not evict anyone who already got in. If a site was exploited before it was updated, the attacker’s access persists through the update. That is why checking matters and why “we updated, so we are fine” is an incomplete answer.

How we verified nothing landed

Our sites were updated to patched versions on the afternoon of July 17, hours after release and before public exploit tooling existed. That happened because the update path on every site we manage is kept in working order, which is unglamorous work that only pays off on days like this one. Sites that drift out of maintenance are exactly the sites where emergency updates fail quietly.

Behind that, the attacks that did arrive hit multiple independent layers of filtering before they could reach WordPress at all, which is why the exploit attempts in our logs are recorded as rejections rather than as requests that were served.

Then we checked anyway: version audits across every site, log analysis across the full attack window including compressed archives, and file integrity verification, administrator account audits, and application password reviews on the highest value properties. The blocking layers held, and the checks are how we know that rather than assume it.

Nothing was compromised. No single product gets the credit for that: the sites were current, the defenses were layered, and a person read the logs afterward.

What happens to a site nobody is watching

Consider the same event on a site with no maintenance plan.

WordPress is a version or two behind because nobody has logged in for months. There is no firewall in front of it. The exploit arrives, as it arrived at everyone, and it works. The attacker installs a webshell that survives every future update, dumps the database including user records and contact form submissions, adds an administrator account, and quietly injects spam into the site’s pages. Often the server itself gets drafted into attacking other sites, which is how the IP ends up blacklisted and the business’s email stops being delivered.

The owner usually finds out weeks later, from Google, or from a customer, or from their host shutting the account down.

None of that requires the attacker to have chosen you. The scanning is automated, and any unpatched site that answers gets the same treatment.

This is what ongoing WordPress maintenance is for: making sure that when a critical vulnerability drops on a Thursday afternoon, your site is already patched before the exploit code is public, already behind layers that reject the attempt, and checked afterward by someone who knows what a compromised site looks like.

If you are not sure who is doing that for your site, or whether anyone is, that is worth finding out. We manage hosting, updates, and security for businesses that would rather never think about a week like this one. Get in touch and we will tell you honestly where your site stands.

Common questions about wp2shell

What is wp2shell?

wp2shell is the name given to an exploit chain combining two WordPress core vulnerabilities disclosed on July 17, 2026: CVE-2026-60137, an unauthenticated SQL injection, and CVE-2026-63030, a route confusion flaw in the REST API batch endpoint. Chained together they allow an attacker to run code on a WordPress server with no login, no password, and no vulnerable plugin required.

What WordPress version fixes wp2shell?

Versions 7.0.2, 6.9.5, and 6.8.6 contain the fix. Note that 7.0.1 is not patched. If your site reports any 6.8, 6.9, or 7.0 version below those three numbers, update immediately.

How do I know if my WordPress site was hacked by wp2shell?

Search your full access logs, including compressed rotated logs, for requests to the batch/v1 endpoint. GET requests that returned 404 are harmless probes. POST requests deserve scrutiny, and any HTTP 207 response after July 17, 2026 from a source you do not recognize is a serious red flag. Also verify core file integrity with wp core verify-checksums, look for PHP files in your uploads directory, and audit your administrator accounts for anything you did not create.

Does updating WordPress remove an attacker who already got in?

No. Updating closes the vulnerability, but it does not remove webshells, rogue administrator accounts, or other persistence an attacker established before the update. If a site was compromised before it was patched, the attacker’s access survives the update, which is why verification matters even after you are on a fixed version.


André Vieira is the Lead Web Developer and Systems Engineer at Muze Development, a WordPress development, design, and maintenance agency. A former security analyst, he runs the hosting infrastructure behind 150+ client sites, and the log analysis in this post is part of his normal week.