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,$_POSTor$_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
- Back up first, then download the suspicious files so you have them as evidence.
- Delete them.
- Stop PHP from running in uploads. On Apache and LiteSpeed hosts, create
wp-content/uploads/.htaccesswith:<FilesMatch "\.(php|phtml|phar|php\d)$"> Require all denied </FilesMatch>On older Apache 2.2 servers use
Deny from allinstead ofRequire all denied. Nginx ignores.htaccess, so there your host needs alocationrule. Even if a file gets in again, it cannot run. - Check the rest of the site: modified core files, unknown administrator users, and plugins you did not install.
- 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.