How to Identify and Remove a PHP Backdoor on Your WordPress Site

TrexHost – Best Web Hosting: Fast, Reliable & Affordable Solutions - Visit: https://trexhost.com

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:

PatternWhat 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 functionsHidden payload that only the attacker can decrypt
file_get_contents or curl fetching a remote URLCommunication 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 dotfileDropping a persistent hidden backdoor
include(...) followed by unlink(...)Executes the dropped file, then deletes it to cover tracks
Unusual global variables like $npDcheckClassBgp, $zeetaGuard 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 all
  • wp-content/plugins/ and wp-content/themes/ — look for files with random or unusual names
  • The WordPress root directory — especially wp-config.php and .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:

  1. TrexHost control panel password — if the attacker has this, they can reset everything else.
  2. FTP/SFTP passwords — and delete any FTP accounts you do not use.
  3. Database password — then update the matching value in wp-config.php.
  4. 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

  1. Upload a temporary test.php to the uploads directory containing: <?php echo "executed"; ?>
  2. Request https://yourdomain.com/wp-content/uploads/test.php in a browser.
  3. Expected result: 403 Forbidden.
  4. If you see executed: contact TrexHost support and ask us to confirm that AllowOverride permits FilesMatch/Require directives on your account.
  5. 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_MODS unless you also intend to disable all plugin/theme installation and automatic updates, which increases patch latency. DISALLOW_FILE_EDIT is 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:

RiskWhat you can do
Another account on the same server is compromised and pivots to your filesTrexHost 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 siteTrexHost 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 infectedTrexHost 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
  • â–¡ .htaccess in wp-content/uploads/ blocks PHP execution (verified with test file returning 403)
  • â–¡ DISALLOW_FILE_EDIT set to true in wp-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:

  1. A backdoor was missed during cleanup, or
  2. 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.

Scroll to Top