Skip to content
PHP security alert Two critical PHP flaws (php2shell) were fixed on 21 October. Is your site's PHP patched? Check in a minute →
OvKit
Menu
Download free

PHP Files in the WordPress Uploads Folder: What They Mean

The uploads folder should hold only media. How to find PHP files there, tell harmless ones from back doors, remove them and stop PHP running in uploads.

The uploads folder, wp-content/uploads, is where WordPress keeps your images, PDFs and other media. None of that is PHP. So a PHP file in uploads is one of the clearest signs that something is wrong, and one of the most common ways attackers keep access to a site after the original hole is closed.

Why attackers use the uploads folder

It is the one folder WordPress itself must be able to write to, so it is writable on almost every host. A vulnerable plugin with a broken upload form, or an attacker who already has admin access, can drop a small PHP file there, often named to blend in: wp-cache.php, image.php, or a random string inside a dated folder like 2024/03/. Visiting that file’s URL then runs it, which gives the attacker a back door that survives password changes and plugin updates.

Find PHP files in uploads

With SSH, from the site’s folder:

find wp-content/uploads -type f -iname '*.php*'

The *.php* pattern also catches tricks like shell.php.jpg or file.phtml. To also catch .phar and other variants, run:

find wp-content/uploads -type f \( -iname '*.ph*' -o -iname '*.phar' \)

Without SSH, open the uploads folder in your host’s file manager and use its search for .php. Some security plugins list them too. The Pro add-on of the Ovanap Admin Toolkit includes this check in its Security Check.

Which ones are normal

A few plugins create small PHP files in their own uploads subfolder. Most are an empty index.php containing only <?php // Silence is golden., which stops anyone listing the folder. Those are harmless. Logging and form plugins sometimes do the same in folders named after themselves.

A PHP file is suspicious when:

  • it sits in a dated media folder (uploads/2025/06/), where only media belongs;
  • it contains eval, base64_decode, gzinflate, assert, $_POST or $_REQUEST, or long unreadable strings;
  • its name looks like a media file or a WordPress core file;
  • it appeared recently and you did not install anything around that date.

What to do

  1. Back up first, then download the suspicious files so you have them as evidence.
  2. Delete them.
  3. Stop PHP from running in uploads. On Apache and LiteSpeed hosts, create wp-content/uploads/.htaccess with:
    <FilesMatch "\.(php|phtml|phar|php\d)$">
      Require all denied
    </FilesMatch>

    On older Apache 2.2 servers use Deny from all instead of Require all denied. Nginx ignores .htaccess, so there your host needs a location rule. Even if a file gets in again, it cannot run.

  4. Check the rest of the site: modified core files, unknown administrator users, and plugins you did not install.
  5. Close the way in: update or remove the plugin with the vulnerable upload, and change all passwords.

Frequently asked questions

Can blocking PHP in uploads break anything?

Rarely. A handful of old plugins ran PHP scripts from their uploads folder. If something breaks, the plugin’s error tells you which folder it needs, and that plugin is worth replacing anyway.

I deleted the files and they came back.

Something on the site recreates them: modified core files, a must-use plugin, an injected line in the theme’s functions.php, or a cron task. A recurring infection usually needs a full clean-up or a professional.