Information security

wp2shell: two harmless bugs, one lost site. How wp2shell works

wp2shell: two harmless bugs, one lost site. How wp2shell works

On July 17, 2026, WordPress released version 7.0.2, together with fixes for the older branches (6.9.5 and 6.8.6). This is not an update like the others. It closes a vulnerability that allows remote code execution with no authentication at all: no password, no account, nothing. And since it is already being exploited in real attacks, the recommendation is blunt: update immediately.

So much for the news, which you will find everywhere. What is rarely explained is how it works. And it is worth understanding, because this flaw is a small masterpiece of logic, and because the way it was discovered says something about the craft of information security that is changing before our eyes.

If you don't run WordPress, feel free to skip to the end: the lesson that matters is there. But if you are fascinated by how an apparently solid system breaks, stay. I will try to tell it without assuming you are a developer.

Two harmless defects that together become a weapon

The chain is called wp2shell and it comes not from one mistake but from two. Taken individually they are almost negligible. Combined, they carry a stranger from nothing to total control of the site.

Defect one: the courier who mixes up the parcels (CVE-2026-63030)

WordPress has a "batch" API, an endpoint meant to send several requests in one go instead of one at a time. Picture it as a counter that accepts a stack of forms all at once.

The counter works in two phases. First it checks all the forms one by one: are they filled out correctly? are the permissions in order? It puts the check results in one list, and the actual forms in another list, in parallel. Then, in a second pass, it takes the check results and pairs them with the forms in order to run them.

The defect lies in a single instruction. When a form is malformed, the code runs continue: it skips to the next one. But in doing so it advances by one position in the list of checks and not in the list of forms. From that moment on, the two lists are out of sync by one.

The result is surreal: request A is checked with request A's rules, but executed with request B's handler. It is like a courier who verifies the address on parcel number one and then delivers parcel number two. All the security checks are passed, except they applied to something else.

In jargon this is called a desync, a misalignment. And it is enough to bypass WordPress's validations.

Defect two: the door that opens only if you knock the right way (CVE-2026-60137)

The second problem is a classic SQL injection, the kind of flaw that lets you inject commands into the database.

There is an API parameter, author__not_in, meant to exclude certain authors from the results. WordPress "cleans" it to prevent abuse: if you pass it a list of values, it checks each element and forces it to be a number. Locked down.

But there is a hole in the logic. If, instead of a list, you pass it a single value, the check does not trigger at all: the data passes through intact and lands straight inside a SQL query. Under normal conditions this hole is unreachable, because to reach that parameter you have to pass through another check that enforces the list form.

Keep this detail in mind: the dangerous door exists, but it is protected by a second door that forces you to knock the right way.

And here the two flaws shake hands

You have already figured out where this goes.

The first defect, the confused courier, makes it possible to have the request checked by a handler that does not look at author__not_in, and then executed by the handler that does use it. The second door is simply bypassed. At that point the attacker slips in their malicious single value, something like 0) OR 1=1 --, and the SQL injection is served.

The authors of the analysis had to nest two misalignments one inside the other, because the batch endpoint itself does not accept requests in the right form. A Russian doll of logic errors. But the principle is the same: one defect unlocks the other.

From reading the database to controlling the site

A SQL injection that reads the database would already be serious. But here something more refined happens, at times almost elegant in its malice.

With the injection, the attacker does not just read: they forge fake posts that WordPress believes are real and holds in memory. From these phantom posts they build, step by step, a ladder to escalate privileges:

  • they insert special content that forces WordPress to materialize their fake objects in the database;
  • they forge a particular kind of post, a changeset, containing setting changes signed with an administrator's identity, because in WordPress every change carries the ID of the user whose authority will apply it;
  • they exploit the internal logic WordPress uses to detect "loops" between related posts, because that logic resets the post without overwriting its content, leaving the payload intact;
  • when the changeset is applied, WordPress calls wp_set_current_user() and for an instant takes on the administrator's identity;
  • in that instant a hook fires that re-runs the entire initial request, this time with administrator privileges.

And in the re-run request there was, from the very start, the order to create a new administrator account. An order that failed earlier for lack of permissions, and that now instead goes through.

From there it was over: the attacker logs in as an administrator, uploads a backdoor plugin and runs code on the server. From nothing, without ever knowing a password.

The detail that impresses is that no step "cracks" a password or a token. Each single piece abuses a legitimate behavior of WordPress. It is a series of perfectly regular moves that, lined up, produce a result that none of them was supposed to allow.

Who found it, and with what

And this is where the story gets interesting beyond the technique.

This chain was not discovered by a team of veterans after months of analysis. It was found by Adam Kues, a researcher at Searchlight Cyber, by feeding an OpenAI model, GPT-5.6 Sol Ultra, a clean copy of the WordPress source code, with no changelog and no hints. Just the code and a request to analyze it.

The model spotted the misalignment, found the hole in the sanitization, built the nested payload to bypass the restrictions, worked out the combination to materialize the fake posts and chained together the entire privilege escalation. It produced a working exploit in a little over ten hours of processing, at a cost of about 25 dollars in API credits. No online research, no database of known flaws: pure code analysis and logical chaining.

Kues's words are worth more than any commentary: "GPT-5.6 Sol Ultra took four hours to write an attack chain that started from a SQL injection and reached remote code execution, while it took me much longer just to understand it."

The title of his research is a punch in the stomach for the industry: exploit brokers pay up to half a million dollars for a WordPress RCE flaw. He found one with 25 dollars and a language model.

Kues reported everything to WordPress, which fixed it and forced the automatic update on vulnerable sites, installing the safe version without asking. A drastic measure, justified by the fact that the firm Patchstack is already seeing exploitation attempts in its customers' logs.

What you need to do, concretely

If you have a WordPress site, the list is short:

  1. Verify you are on 7.0.2 (or 6.9.5 / 6.8.6 on the older branches). Many sites have already been updated automatically, but check: Dashboard → Updates.
  2. Look for administrator accounts you don't recognize. If the flaw was exploited before the patch, an unwanted guest user may have been left behind.
  3. Check recently installed plugins, especially ones you don't remember uploading. The backdoor arrives as a plugin.
  4. If you find anything suspicious, an update is not enough: the site must be considered compromised and cleaned from scratch, restoring from a backup taken before the attack.

The lesson that matters, WordPress or not

Beyond the specific case, this story says two things that concern anyone with something exposed on the internet.

The first is that the most dangerous flaws are almost never a single glaring mistake. They are combinations. Two harmless behaviors that, slotted together in the right order, open a door nobody designed. This is why security is not solved by plugging the flaw of the month: it is built in layers, taking for granted that sooner or later one level will give way.

The second is more uncomfortable. The cost of finding serious vulnerabilities is collapsing. What once required an expert and weeks of work can today come out of a model in ten hours and twenty-five dollars. In this story the tool was in the hands of an honest researcher, who gave warning before anyone else. Next time it might not be.

That is not a good reason to panic. It is an excellent reason to stop postponing updates, to keep an eye on what is exposed, and to treat security maintenance as something continuous rather than an intervention to make when you happen to remember. The defense does not have to be brilliant. It has to be constant.

بقلم Claudio