Key takeaways
- A webshell is a script uploaded to your web server that lets an attacker run commands through a browser.
- Webshells are usually disguised as images, cache files or plugin files, and there is rarely only one.
- Deleting the file is not enough: you must close the entry point and remove every other form of persistence.
- Blocking PHP execution in upload folders stops the most common webshell placement outright.
- Keep a copy of every webshell you remove as evidence before you delete it from the live site.
What is a webshell?
A webshell is a small script, usually PHP on WordPress and Linux hosting, that an attacker uploads to your web server so they can control it through a browser. Once it is in place, they can browse files, upload more malware, read your database credentials and run system commands, all while looking like normal web traffic.
Think of a webshell as a spare key the intruder cut while they were inside. The original break-in might have been a vulnerable plugin, a stolen password or a neighbouring site on the same server. The webshell is what lets them come back tomorrow, next week or after you have "fixed" the obvious damage.
Webshells range from a single line of obfuscated code to full file-manager kits with a login page, a terminal, a database browser and a mass-defacement tool. Kits such as ALFA and KINGSMAN, which we regularly find during server malware removal, fall into the second group: they are polished, password-protected control panels built for managing many compromised sites at once.
How do webshells get onto a server?
Webshells arrive through whatever weakness the attacker found first: an unpatched plugin or theme with a file-upload flaw, a stolen WordPress admin or FTP password, a compromised site sharing the same server user, or an exposed file manager. The webshell is the second stage; the entry point is the problem you actually need to fix.
The most common routes we see are:
- Vulnerable upload handlers. A plugin form that accepts files without checking type lets an attacker upload
image.phpstraight intowp-content/uploads. - Stolen admin credentials. With admin access, the built-in theme and plugin editors will happily write PHP to disk.
- Cross-site contamination. On servers where several sites run as one system user, one hacked site can write into every other site. Our guide to VPS security explains why.
- Leaked FTP, SFTP or control panel logins. Old credentials in a developer's config file or a phished hosting account.
Every webshell tells a story about how it arrived. File timestamps, web server access logs and the user that owns the file usually point back to the entry point, which is why forensic analysis comes before clean-up.
What does a webshell look like?
Most webshells are deliberately hard to read. They hide behind encoding functions such as base64_decode, gzinflate and str_rot13, build function names from string fragments, and take their instructions from request parameters or cookies. File names are chosen to blend in: wp-cache.php, class-wp-rest.php or favicon_5d1e.ico.
The examples below are illustrative, defanged and truncated. They show the patterns to look for, not working code.
# One-liner style: runs whatever arrives in a request parameter
<?php @$_="as"."se"."rt"; @$_(str_rot13(base64_decode($_REQUEST['...']))); [truncated]
# Obfuscated loader: a long encoded blob unpacked at runtime
<?php $k='x7'; eval(gzinflate(base64_decode('7X1rc9s2su/7V8C6VQ... [truncated 48 KB]')));
# Kit-style login gate seen in ALFA / KINGSMAN-type panels
if(md5($_POST['pass'] ?? '') !== '5f4dcc3b...'){ header('HTTP/1.0 404 Not Found'); exit; }
Notice the last pattern: many kits return a fake 404 page to anyone without the password. If you visit the file in a browser it looks as though nothing is there, which is exactly why "I checked and the file is gone" is not proof of a clean site.
Warning: do not open suspected webshells in a browser or run them to "see what they do". Copy them to an isolated location for analysis and work from the copy.
How do you find webshells on a server?
Finding webshells means combining several signals: PHP files where PHP should never be, files changed around the time of the incident, encoded or dynamically executed code, and files that do not match the official WordPress, plugin or theme checksums. No single grep catches everything, so use all four checks together.
- Look for PHP in upload folders. WordPress never needs executable PHP inside
wp-content/uploads. Anything found there deserves investigation. - Sort by modification time. Attackers often backdate files, but new files still cluster around the intrusion window.
- Search for dangerous functions. Expect false positives from legitimate plugins; each match needs reading, not deleting blindly.
- Verify checksums. WP-CLI can compare core and plugin files against the official copies on WordPress.org.
# 1. PHP files inside uploads (should return nothing)
find /var/www/example.co.uk/wp-content/uploads -type f \( -name "*.php" -o -name "*.phtml" -o -name "*.phar" \)
# 2. PHP files modified in the last 30 days, newest first
find /var/www -type f -name "*.php" -mtime -30 -printf '%TY-%Tm-%Td %TH:%TM %u %p\n' | sort -r | head -50
# 3. Common obfuscation and execution patterns
grep -rlE "eval\(|gzinflate\(|str_rot13\(|base64_decode\(|assert\(|create_function" /var/www --include="*.php"
# 4. Compare WordPress core and plugins with official checksums
wp core verify-checksums --path=/var/www/example.co.uk
wp plugin verify-checksums --all --path=/var/www/example.co.uk
On a server hosting many sites, repeat this for every document root and check files owned by unexpected users. The PatientZero Forensic scan (dfir-fast) and Malware sweep (malware-intelligence) profiles run these checks, and many more, across every site on the server in one pass.
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.
How do you remove a webshell safely?
Safe webshell removal follows a fixed order: preserve evidence, contain access, remove every malicious file, remove any other persistence, then close the entry point and rotate credentials. Deleting the one file you found while the attacker still has a cron job, a rogue admin user or a second shell simply starts the cycle again.
- Preserve. Copy suspicious files, with their timestamps, to a quarantine folder outside the web root and record a hash of each.
- Contain. Put the site behind a maintenance response or firewall rule so the shell can no longer be reached while you work.
- Remove. Delete confirmed webshells and replace modified core, plugin and theme files with clean copies from official sources.
- Hunt persistence. Check crontabs, systemd services,
.htaccessand.user.inifiles, rogue WordPress administrators and SSHauthorized_keys. - Close the door. Patch or remove the vulnerable component, then rotate WordPress, database, SFTP, SSH and hosting passwords and the WordPress salts.
# Quarantine with hashes before deleting anything
mkdir -p /root/quarantine/2026-09-29
sha256sum /var/www/example.co.uk/wp-content/uploads/2026/08/thumb-cache.php >> /root/quarantine/2026-09-29/hashes.txt
cp -p /var/www/example.co.uk/wp-content/uploads/2026/08/thumb-cache.php /root/quarantine/2026-09-29/
# Then check for other persistence
crontab -l -u www-data
find /var/www -name ".user.ini" -o -name ".htaccess" -newer /var/www/example.co.uk/wp-config.php
Tip: if a webshell keeps reappearing after you delete it, something is re-creating it. Our guide on why malware keeps coming back covers the cron jobs and backdoors responsible.
How do you stop webshells coming back?
The single most effective control is to stop PHP executing anywhere users can upload files. Combine that with prompt updates, separate system users per site, disabled in-dashboard file editing and ongoing file-integrity monitoring, and a newly dropped webshell either cannot run or is detected quickly.
# Block PHP execution in WordPress uploads
location ~* ^/wp-content/uploads/.*\.(php|phtml|phar)$ {
deny all;
}
<FilesMatch "\.(php|phtml|phar)$">
Require all denied
</FilesMatch>
| Control | What it stops |
|---|---|
| No PHP in uploads | The most common webshell location |
DISALLOW_FILE_EDIT in wp-config.php | Admins (or stolen admin sessions) writing PHP via the dashboard editors |
| One system user per site | One hacked site writing shells into its neighbours |
| File-integrity monitoring | New or changed PHP files going unnoticed |
| Prompt plugin and theme updates | Known upload and file-write vulnerabilities |
Our full WordPress hardening checklist goes further, and the PatientZero Harden playbooks apply these controls consistently across every site on a server.
When should you get professional help?
Get help if you have found more than one webshell, if files reappear after deletion, if the server hosts several sites, or if you find signs of system-level access such as unknown cron jobs, services or SSH keys. Those point to a compromise deeper than one WordPress install.
A webshell on a server often sits alongside reverse shells, rogue users and scheduled re-download jobs. Removing them properly means investigating the whole server, not just the site that showed symptoms. PatientZero connects over SSH, runs a forensic scan across every site, quarantines what it finds with evidence kept, fixes the entry point and hardens the server afterwards. Unlimited malware removal is included on every plan.
If you think you have a webshell right now, start with our security triage, or go straight to emergency help and we will start triage as soon as you get in touch.
Frequently asked questions
Is a webshell the same as a backdoor?
A webshell is one type of backdoor. The term backdoor covers any hidden way back into a system, including rogue admin accounts, SSH keys, cron jobs and reverse shells. A webshell specifically is a script served by the web server, so it is reached through a browser or HTTP request.
Will my security plugin detect webshells?
Some, but not all. Plugins scan from inside WordPress, so they can miss shells outside the WordPress directory, in other sites on the same server, or heavily obfuscated variants. Server-side scanning looks at the whole file system, cron, services and users as well as the site files.
Can I just restore a backup to remove a webshell?
Only if you know the backup predates the compromise and you fix the entry point before going live. Many restores bring the webshell or the original vulnerability straight back. Restoring also does nothing about server-level persistence such as cron jobs or rogue SSH keys.
Why did the webshell return a 404 when I visited it?
Many webshell kits show a fake "Not Found" page unless the correct password or cookie is sent. A 404 in your browser does not mean the file is harmless or absent. Check the file system directly rather than relying on what the browser shows.
Should I keep a copy of the webshell?
Yes. Keep a copy in a quarantine folder outside the web root, with its hash and original timestamps. It is useful evidence for working out the entry point, for any breach assessment you need to make, and for spotting the same kit elsewhere on your server.