WordPress Hardening – Part 2: Securing the Uploads Directory

An abstract picture representing the directory structure of a computer system.

How to Lock Down the Most Vulnerable Directory in WordPress

If you only implement one hardening step from this entire series, make it this one. The /wp-content/uploads/ directory is the single most common place attackers hide malware, and most WordPress sites leave it wide open without realizing it.

This article walks through how to test your uploads directory, understand the risks, and lock it down safely.

Why the Uploads Directory Is a Prime Target

The uploads folder is designed to store:

  • images
  • PDFs
  • media files
  • documents

But here’s the problem:

Uploads is writable.
WordPress, plugins, and even visitors (via forms) can place files there.

Some servers allow PHP execution in uploads by default.
If an attacker uploads a malicious .php file and the server executes it, they effectively gain remote code execution – the holy grail of website compromise.

Malware loves hiding in uploads.
Attackers often disguise malicious files as:

  • image.php
  • style.php
  • wp-ajax.php
  • favicon.php

If PHP execution is allowed, these files can run silently.

Step 1 – Test Whether PHP Can Execute in Uploads

This is the most important test in the entire series.

  • Create a file named test.php with this content:
<?php echo "PHP is running"; ?>
  • Upload it to:
/wp-content/uploads/2026/
(or any year/month folder)
  • Visit it in your browser:
https://yourdomain.com/wp-content/uploads/2026/test.php

Interpret the result:

  • If you see “PHP is running” then your site is vulnerable.
  • If you get a 403 Forbidden = good.
  • If you get a 404 Not Found = also good.
  • If it downloads instead of running = safe.

If PHP executes, you need to fix it immediately.

Step 2 – Block PHP Execution in Uploads

This is the safest and most widely recommended hardening rule for WordPress.

Add this .htaccess file inside /wp-content/uploads/

# Prevent PHP execution in uploads
# Compatible with Apache 2.2 and 2.4+
<IfModule mod_authz_core.c>
    <FilesMatch "\.php$">
        Require all denied
    </FilesMatch>
</IfModule>
<IfModule !mod_authz_core.c>
    <FilesMatch "\.php$">
        Order allow,deny
        Deny from all
    </FilesMatch>
</IfModule>

This tells Apache:

  • “If a file ends in .php, block all access to it.”
  • “Do not execute it or allow anyone to view it.”
  • “Use the appropriate blocking method depending on the Apache version.”

Why this is safe:

  • WordPress does not need to run PHP in uploads
  • Plugins do not need to run PHP in uploads
  • Themes do not need to run PHP in uploads

If a plugin does try to run PHP from uploads, that plugin is broken or dangerous.

Run your test in the browser again. This time you should see a 403 (Forbidden) or 404 (Page Not Found) error. That is what you want.

Once your wp-content/uploads directory is secured, delete the test file. It is best practice to remove files you no longer use.

Step 3 – Disable Directory Indexing

Directory indexing allows visitors to see a list of files in a folder if no index file exists.

Try visiting:

https://yourdomain.com/wp-content/uploads

If you see a list of folders that means indexing is enabled.
This isn’t as dangerous as PHP execution, but it leaks information about:

  • your media
  • your folder structure
  • your upload history

To disable indexing site-wide, add this to your root .htaccess file (the one in your WordPress installation’s main directory, where wp-config.php is located)

# Disable directory indexing
Options -Indexes

Note: Most quality hosts (including GoDaddy) disable this by default at the server level, so you may already be protected. Always test first. If you get a 403 error when visiting your uploads directory, you’re already secure and don’t need to add anything.

Step 4 – Clean Up Any Suspicious Files

Now that uploads is locked down, it’s a good time to scan for suspicious files.

Look for:

  • .php files
  • .phtml files
  • .php5, .php7, .phar
  • files with double extensions like image.jpg.php
  • files with random names like a7d9f.php

If you find any, investigate or delete them.

Why This Step Alone Stops Many Attacks

Blocking PHP execution in uploads prevents:

  • backdoor shells
  • malware droppers
  • remote code execution
  • plugin upload vulnerabilities
  • form upload exploits
  • image upload bypasses
  • fake image files containing PHP

Even if an attacker uploads a malicious file, it becomes harmless.

This is one of the most effective hardening steps you can take.

Coming Up Next: Part 3 – Cleaning and Understanding Your Rewrite Rules

In the next article, we’ll dig into .htaccess:

  • how WordPress uses it
  • how plugins modify it
  • how to clean it
  • how to avoid conflicts
  • how to add safe hardening rules

This is where your site’s security and performance start to come together.