Does your WordPress website sometimes send visitors to a completely different website when they open it? This is one of the most common signs that malicious code has been placed inside your site’s files. The redirect may only happen for certain visitors, certain devices, or certain times of day, which makes it easy to miss.
Other warning signs include:
- Your site loads slowly or shows unexpected pop-ups
- Search engines warn visitors that your site is unsafe
- You see files in cPanel File Manager that you did not create
- Your hosting provider or a security scanner has flagged suspicious files
- Your site sends traffic to domains you do not recognize
If any of these apply to you, the first step is to understand what you are looking at. The code below is a typical PHP webshell dropper — a type of backdoor that lets an attacker run commands on your server. You may have found it yourself in File Manager, or a malware scanner may have flagged it. If you are unsure whether a file is malicious, look for the patterns described below.
What malicious code looks like
A backdoor of this type usually contains several of the following characteristics:
php
<?php @ini_set('display_errors', '0');
error_reporting(0);
global $zeeta;
if (!$npDcheckClassBgp && !isset($zeeta)) {
$ea = '_shaesx_'; $ay = 'get_data_ya'; $ae = 'decode';
$ea = str_replace('_sha', 'bas', $ea);
// ... builds "base64_decode" from pieces ...
$pass = "Zgc5c4MXrK42MQ4F8YpQL/+fflvUNPlfnyDNGK/X/wEfeQ==";
Red flags to look for in any PHP file:
| Pattern | What it means |
|---|---|
@ini_set('display_errors', '0') and error_reporting(0) | Hides errors so the attacker’s activity does not appear in logs |
Strings assembled from pieces, e.g. str_replace('_sha', 'bas', '_shaesx_') | Obfuscation to evade static scanners; the result here is base64_decode |
base64_decode combined with custom XOR functions | Hidden payload that only the attacker can decrypt |
file_get_contents or curl fetching a remote URL | Communication with a command-and-control server |
preg_match('#gogo(.*)enen#is', ...) | Extracting a payload between marker strings |
Writing a file named .default, .algo, or another hidden dotfile | Dropping a persistent hidden backdoor |
include(...) followed by unlink(...) | Executes the dropped file, then deletes it to cover tracks |
Unusual global variables like $npDcheckClassBgp, $zeeta | Guard flags to prevent the script from running twice |
Where to look
Backdoors are most commonly found in:
wp-content/uploads/— a clean uploads directory should contain no PHP files at allwp-content/plugins/andwp-content/themes/— look for files with random or unusual names- The WordPress root directory — especially
wp-config.phpand.htaccess - Hidden dotfiles such as
.default,.algo,.cache.php
If you found a file matching the patterns above, treat the site as compromised and continue with Part 1. Do not simply delete the file and assume you are done — the attacker may have left multiple backdoors, and the original entry point is still open.
TrexHost note: If you are not comfortable inspecting PHP files manually, install a scanner such as Wordfence (free tier) or Deep Malware Cleaner. It will flag the patterns above for you. You can also open a support ticket from your TrexHost client area and our team will review the file for you.
Part 1 — Contain the Compromise
Complete these steps first. They cut off the attacker’s ability to re-enter before you begin cleaning files.
1.1 Rotate all credentials (in this order)
Changing only the WordPress admin password is not enough. Work through every access layer:
- TrexHost control panel password — if the attacker has this, they can reset everything else.
- FTP/SFTP passwords — and delete any FTP accounts you do not use.
- Database password — then update the matching value in
wp-config.php. - All WordPress administrator passwords — not just your own account.
TrexHost tip: You can reset your control panel password directly from the control panel: hover over your name in the top-right corner and select Change Password.
1.2 Reset WordPress security keys and salts
Open wp-config.php in TrexHost control panel’s File Manager and locate the “Authentication Unique Keys and Salts” block. Replace the entire block with a fresh set from the official WordPress key generator (https://api.wordpress.org/secret-key/1.1/salt/).
Effect: All existing login sessions are invalidated immediately, including any session cookies the attacker may have stolen.
1.3 Audit administrator accounts
In WordPress Admin → Users, review every account with the Administrator role. For any account you do not recognize:
- Record its registration date and email before acting.
- Delete it or downgrade it to Subscriber.
Part 2 — Block PHP Execution in the Uploads Directory (Highest Priority)
The backdoor’s core technique is writing a PHP file into a web-accessible directory and executing it. Blocking PHP execution in wp-content/uploads/ neutralizes this entire class of attack. WordPress never legitimately needs to execute PHP from the uploads directory.
2.1 Open File Manager
Log in to your TrexHost control panel and open Files -> File Manager. Navigate to your WordPress root directory.
2.2 Locate the uploads directory
Navigate to wp-content/uploads/.
2.3 Create or edit .htaccess
If no .htaccess file exists in that directory, create one. If one exists, back it up before editing. Add the following:
apache
<FilesMatch "\.(php|phtml|php[0-9]|pht|phar)$">
Require all denied
</FilesMatch>
Why not php_flag engine off?
That directive only works under mod_php. TrexHost shared servers run PHP-FPM, where it has no effect. The FilesMatch + Require all denied approach operates at the Apache layer and works regardless of the PHP handler.
2.4 Verify the protection works
- Upload a temporary
test.phpto the uploads directory containing:<?php echo "executed"; ?> - Request
https://yourdomain.com/wp-content/uploads/test.phpin a browser. - Expected result:
403 Forbidden. - If you see
executed: contact TrexHost support and ask us to confirm thatAllowOverridepermitsFilesMatch/Requiredirectives on your account. - Delete the test file.
Part 3 — Disable the Built-in File Editors
If an attacker regains admin access, WordPress’s built-in plugin and theme editors allow direct PHP injection without any file upload. Add this line to wp-config.php, above the /* That's all, stop editing! */ comment:
php
define( 'DISALLOW_FILE_EDIT', true );
This removes the Appearance Editor and Plugin Editor menus from the dashboard.
Note: Do not use
DISALLOW_FILE_MODSunless you also intend to disable all plugin/theme installation and automatic updates, which increases patch latency.DISALLOW_FILE_EDITis the safer minimum.
Part 4 — Remove Residual Backdoors
The dropper described above writes a hidden .default file, but variants exist. Without SSH, use TrexHost control panel’s File Manager to search manually.
4.1 Scan the uploads directory for PHP files
In wp-content/uploads/, search for any file ending in .php, .phtml, or .phar. A clean WordPress uploads directory contains zero PHP files. Download anything you find for your records, then delete it from the server.
4.2 Inspect recently modified files
In both public_html/ and wp-content/, sort files by Last Modified (descending) and review anything changed in the past several days. Prioritize:
wp-config.php.htaccess- Theme
functions.php - Any PHP file with an unusual or random name
4.3 Run a malware scanner plugin
Install a free scanner such as Wordfence (free tier) or Deep Malware Cleaner. These scan wp-content and flag the signatures listed in the “Is Your Website Redirecting” section — eval(base64_decode(...)), shell_exec, preg_replace with the /e modifier, and PHP files in upload directories. Review flagged high-risk files and delete confirmed threats.
Caution: Scanners produce false positives. Verify a file is malicious before deleting, especially inside active plugins or themes.
Part 5 — Reduce the Attack Surface
5.1 Delete unused plugins and themes
Every inactive plugin and theme is code on your server that can be exploited even when not active. Delete anything not in use. Never install “nulled” or pirated plugins — they frequently ship with backdoors pre-installed.
5.2 Update everything
Update WordPress core, all active plugins, and all active themes to their latest versions. Known vulnerabilities in outdated components are the most common entry point on shared hosting.
Part 6 — Shared Hosting Constraints at TrexHost
On shared hosting, you cannot control server-level configuration. Understand these limits and what TrexHost provides:
| Risk | What you can do |
|---|---|
| Another account on the same server is compromised and pivots to your files | TrexHost enforces per-account isolation and open_basedir restrictions. If you suspect cross-account contamination, open a ticket and we will investigate. |
| No WAF in front of your site | TrexHost applies server-level filtering, but for defense in depth we recommend adding Cloudflare (free tier) at the DNS level to filter malicious requests before they reach the origin. |
| Backups may be unreliable or already infected | TrexHost performs automated account backups, but you should also take manual backups via control panel and download them to your local machine. Never restore a backup taken after the infection date. |
Verification Checklist
Before considering your site clean, confirm each item:
- â–¡ All control panel, FTP, database, and WordPress admin passwords rotated
- â–¡ WordPress salts regenerated
- â–¡ Unknown administrator accounts removed
- â–¡
.htaccessinwp-content/uploads/blocks PHP execution (verified with test file returning 403) - â–¡
DISALLOW_FILE_EDITset totrueinwp-config.php - â–¡ No PHP files remain in
wp-content/uploads/ - â–¡ Malware scanner reports clean
- â–¡ All unused plugins/themes deleted
- â–¡ WordPress core, plugins, and themes updated
- â–¡ Clean backup downloaded locally
If the Infection Returns
Recurring suspicious files after completing all steps indicate one of two conditions:
- A backdoor was missed during cleanup, or
- The original entry point (likely an unpatched plugin vulnerability) remains open.
In either case, the safest path is to restore from a backup taken before the infection date, then immediately re-apply Part 2 and Part 3 before reconnecting the site to the internet. After restoration, audit each plugin’s version history and update record to identify the likely entry vector.
If you need help identifying the entry point, open a support ticket from your TrexHost control panel and include the malicious file’s path and any scanner output. Our team can review server logs for the initial request that dropped the backdoor.
