Key takeaways

  • wp2shell describes attackers turning WordPress admin or plugin access into a PHP webshell with server-level control.
  • The usual routes are stolen admin passwords, rogue admin accounts created through vulnerable plugins, and abuse of the theme editor or plugin upload.
  • Look for PHP in uploads, unfamiliar must-use plugins, recently installed plugins and POST requests to the editor in access logs.
  • Removing the visible shell is not enough: rogue admins, cron jobs and secondary shells must all go, and every credential must be rotated.
  • Disabling file editing, enforcing two-factor authentication and blocking PHP in uploads breaks the pattern.

What is wp2shell?

wp2shell is the name we use for a common attack pattern: an attacker gains WordPress administrator or plugin-level access and turns it into a PHP webshell on the server. Once the webshell is in place, the attacker no longer needs WordPress at all. They can browse files, read database passwords, run commands and spread to other sites.

The pattern matters because it changes the scale of the problem. A hacked WordPress admin account is serious; a webshell is worse, because it gives the attacker direct access to the file system with the permissions of the web server user. On shared hosting or a multi-site VPS, that often means access to every site under the same account.

wp2shell is not a single vulnerability. It is the chain that follows many different ones: a leaked password, a plugin flaw that lets an unauthenticated visitor create an admin, or an insecure file upload. Whatever opens the door, the next steps look very similar, which is why the clean-up process in this guide applies broadly. For background, see webshells explained.

How does a wp2shell attack work?

A wp2shell attack usually works in four stages: the attacker gains admin-level access, uses a built-in WordPress feature such as the theme editor or plugin uploader to write PHP to disk, sets up persistence so the shell survives a clean-up, and then pivots to the rest of the server. Each stage leaves traces you can look for.

StageTypical methodWhere to look
1. AccessStolen or brute-forced password; rogue admin created via a vulnerable pluginwp_users, login logs, access logs
2. Write PHPTheme or plugin editor; uploading a malicious plugin ZIP; abusing a file upload featureTheme functions.php, new plugin folders, uploads
3. PersistMust-use plugins, extra shells with innocent names, hidden admins, cron jobswp-content/mu-plugins, crontab, wp_options
4. PivotRead wp-config.php files, infect sibling sites, reverse shells, OS persistenceOther sites, /tmp, systemd units, running processes

Stage two is the moment WordPress access becomes server access. A malicious "plugin" can be nothing more than a ZIP file containing a single PHP file with a plugin header, uploaded through Plugins > Add New > Upload. WordPress installs it like any other plugin, and the shell is live.

The theme editor route is even quieter. The attacker opens Appearance > Theme File Editor, adds a line of PHP to the top of functions.php or 404.php, and saves. No new files appear, so checks that only look for unfamiliar files miss it completely. Many attackers then use that first foothold to write a second, standalone shell somewhere less obvious and remove their edit from the theme, leaving very little behind in the place you would naturally look first.

How do you detect a wp2shell infection?

To detect a wp2shell infection, look for PHP files where they should not be, plugins and must-use plugins you did not install, administrator accounts you do not recognise, and access log entries showing POST requests to the plugin uploader or theme editor. Check every site on the server, because the shell may be planted in a neighbour.

# PHP files in uploads (should normally be none)
find wp-content/uploads -type f -name "*.php"
wp-content/uploads/2026/07/.cache/index.php
# Must-use plugins run automatically and are often overlooked
ls -la wp-content/mu-plugins/
-rw-r--r-- 1 www-data www-data 3120 Aug 14 03:12 wp-session-handler.php
# Common webshell and obfuscation markers
grep -rlE "eval\(|base64_decode\(|gzinflate\(|shell_exec\(|assert\(" wp-content --include=*.php
# Evidence of the editor or plugin uploader being used
grep -E "POST /wp-admin/(theme-editor|plugin-editor|update)\.php" /var/log/nginx/access.log

Treat the output as leads, not verdicts. Some legitimate plugins use functions such as base64_decode. What matters is the combination: an obfuscated file in uploads, created at 03:12 on the same night a new admin account appeared and the plugin uploader was used, tells a clear story.

Tip: webshells from kits such as ALFA and KINGSMAN often set a password prompt or a blank page so that they look harmless if you open them in a browser. Never judge a file by what it displays; read the source.

Our Forensic scan (dfir-fast) automates these checks across every site on the server, correlating file times, users, cron jobs and logs into a single timeline.

Security triage

Is your site showing any of this?

Tell us what you’re seeing in two minutes and we’ll tell you what it means and what to do next. Hacked right now? Get emergency help.

Start the triage

How do you remove a wp2shell infection?

To remove a wp2shell infection, contain the server first, take a forensic backup, then remove every webshell, rogue plugin and rogue admin, replace WordPress core from a clean source, clean the database, remove server-level persistence and rotate every credential. Removing only the shell you found almost always leads to re-infection.

  1. Contain. Put affected sites into maintenance mode and, if possible, restrict wp-admin to your own IP address while you work.
  2. Preserve evidence. Take a full copy of files, databases and logs before changing anything. Record file hashes.
  3. Remove rogue access. Delete unknown administrator accounts and destroy all sessions so existing logins are forced out.
  4. Quarantine shells. Move webshells, unknown mu-plugins and malicious plugin folders out of the web root into a quarantine area. Do not simply delete them; they are evidence.
  5. Replace core and plugins. Reinstall WordPress core and every plugin and theme from official sources rather than trying to clean them line by line.
  6. Clean the database. Search wp_options, wp_posts and widgets for injected scripts and unexpected autoloaded options.
  7. Check the server. Review crontab, systemd services, /tmp and running processes for re-infection loops and reverse shells.
  8. Rotate credentials. Change WordPress, database, SFTP, SSH and hosting panel passwords, and regenerate the salts in wp-config.php.

Our step-by-step WordPress malware removal guide covers the clean-up in more depth, and why malware keeps coming back explains the persistence techniques to check for.

How do you stop wp2shell happening again?

To stop wp2shell happening again, break each stage of the chain: protect admin access with unique passwords and two-factor authentication, remove WordPress's ability to write PHP through the dashboard, block PHP execution in uploads, keep plugins patched and audit administrator accounts regularly. Each control alone helps; together they make the pattern very hard to complete.

Two lines in wp-config.php remove the dashboard file editor and, optionally, the ability to install or update plugins from the dashboard:

// Remove the theme and plugin file editors
define( 'DISALLOW_FILE_EDIT', true );
// Also block plugin/theme installs and updates from wp-admin
// (only if updates are handled another way, e.g. WP-CLI or deployment)
define( 'DISALLOW_FILE_MODS', true );

And on Apache, a small .htaccess file in wp-content/uploads stops uploaded PHP from running:

<FilesMatch "\.(php|phtml|phar)$">
  Require all denied
</FilesMatch>

On Nginx, the equivalent is a location block that denies PHP under the uploads path. Our Harden playbooks apply these and other controls consistently across every site on a server, and the full list is in our WordPress hardening checklist.

When does wp2shell become a server problem?

wp2shell becomes a server problem as soon as the webshell has been used to reach beyond the original site. Signs include infected files in neighbouring sites, cron jobs that re-download malware, reverse shell processes, new system users or services, and changed system binaries. At that point, a WordPress-only clean-up will not hold.

In one anonymised case we handled, a single compromised admin account on one site led to webshells across every site on the VPS, a crontab entry re-downloading the shell every minute, a gsocket reverse shell and a rogue VPN node giving the attacker a private route back in. Cleaning WordPress alone would have been undone within sixty seconds. You can read how it was resolved in our root compromise case study.

If you find a reverse shell, unknown system users or modified system binaries, assume the attacker had root-level access. Get specialist help before attempting a clean-up in place; a clean rebuild may be the safer route.

PatientZero's server malware removal covers the full chain, from WordPress admins to systemd persistence, and every plan includes unlimited malware removal. If you are dealing with a live infection now, go to our emergency page or call 01932 593642.

Frequently asked questions

Is wp2shell a specific vulnerability?

No. We use wp2shell as a name for an attack pattern rather than one flaw. Many different weaknesses, from stolen passwords to plugin bugs that allow rogue admin accounts, can lead to the same outcome: an attacker using WordPress access to place a PHP webshell on the server. The clean-up approach is similar whatever the entry point.

Can a security plugin find a wp2shell webshell?

Sometimes, but not reliably. Webshells are frequently obfuscated, renamed to look like core files or placed in must-use plugins and other sites on the server. Some attackers deactivate security plugins as soon as they have admin access. Server-side scanning that checks files, users, cron jobs and processes is far more thorough.

Should I delete webshell files or keep them?

Move them out of the web root into a quarantine area rather than deleting them. They are evidence that helps identify the entry point, the timeline and whether data was accessed, which may matter if you need to assess a UK GDPR breach report. Record file hashes before moving anything.

Does disabling the file editor stop wp2shell completely?

It removes one common route but not all of them. An attacker with admin access may still upload a malicious plugin unless plugin installs are also disabled, and some plugin flaws allow file writes directly. Combine DISALLOW_FILE_EDIT with two-factor authentication, prompt patching and blocking PHP execution in uploads.

How long does a wp2shell clean-up take?

It depends on how far the attacker got. A single site with one shell and a rogue admin can often be cleaned the same day. A server with several infected sites and operating system persistence takes longer, because every site and system component has to be checked before the clean-up can be trusted.

PatientZero Incident Response Team · Digital forensics and incident response

Written by the PatientZero incident response team: the engineers who investigate and clean compromised WordPress sites and Linux servers every week.