Disallow direct access to PHP files in wp-content/uploads/

Secure wp-content/uploads in Linux Apache and Windows Server IIS

It’s recommended to disallow access to and execution of PHP files in wp-content/uploads folder. Preferably and in my opinion without the use of a security plugin. Denying access to PHP files in WordPress wp-content/uploads folder is easily achieved with a .htaccess file on Linux Apache, or web.config on Windows Server IIS, and here is how.

Deny PHP execution for Windows Server IIS and Linux Apache

As said, it is recommended to deny PHP execution in folders like WordPress wp-content/uploads. A lot of malware is uploaded to that folder and used as and entry point. Additional malware and PHP backdoors are uploaded from there. So disable PHP execution in wp-content/uploads! I’ve written about securing WordPress uploads folder before.

Windows Server IIS web.config

The easiest method in IIS to disable PHP execution in a folder is to create a web.config file with an accessPolicy for handlers. Such an accessPolicy tells IIS what a PHP hander is allowed to do: execute, read, or read/write. Using this technique you disable the execution of PHP completely for that particular folder.

Protip: you’ll find more information about IIS Handlers in IIS’ documentation.

In IIS Manager:

  • In IIS Manager, click through to your web site
  • double click “Handler Mappings
  • search for PHP and double click
  • click Request Restrictions
  • click the tab Access
  • Set Script to Read
Read this too:   How to disable SMBv1 in Windows 10 and Windows Server

Did you know you can use Windows Server File Server Resource Manager File Screens to block the upload of vulnerable WordPress plugins? Read all about it in Deny vulnerable WordPress plugins using Windows Server File Server Resource Manager’s File Screens.

Using a web.config file directly.

Copy and paste the following XML into a new file and save it as web.config:

<?xml version="1.0" encoding="UTF-8"?>
		<!-- deny PHP execution per IIS accessPolicy -->
		<handlers accessPolicy="Read"/>

In PowerShell (and appcmd.exe):

Use the following PowerShell and appcmd.exe commands to configure an accessPolicy for handlers (where example.com is your website):

# PowerShell, WebAdministration
Set-WebConfiguration "/system.webServer/handlers/@accessPolicy" -value "Read" -PSPath "MACHINE/WEBROOT/APPHOST/example.com/wp-content/uploads"

# AppCmd.exe
appcmd.exe set config "example.com/wp-content/uploads" /section:handlers /accessPolicy:Read

Caveat: by setting an accessPolicy to “Read”, you basically disable all configured handlers, not just PHP.

Disable PHP execution in a selected directory on Linux Apache

There are several methods to disable PHP execution in Apache using a .htaccess file. I’ll mention them here in short:

SetHandler: use SetHandler default-handler to send the file using the default_handler(), which is the handler used by default to handle static content. It just renders the PHP as text.

In your wp-content/uploads/.htaccess file, add:

# use <Files *> if appropriate
<Files *.php>
        SetHandler default-handler

Mod_authz_core .htaccess access control: you can deny access to PHP files using Apache access control in mod_authz_core module. It’ll send a 403 response for requests to *.php files. Add to your .htaccess file:

<Files *.php>
	# Apache 2.2
	<IfModule !mod_authz_core.c>
		Order Deny,Allow
		Deny from all
	# Apache 2.4.6+
	<IfModule mod_authz_core.c>
		Require all denied

Please note the condition if the module mod_authz_core.c is available. This is important as explained in the above linked article.

Read this too:   Set IIS Application Pool recycle defaults to Specific Times, not Regular Time Interval

Mod_Rewrite: rewrite and forbid requests to *.php files. It’s easy to use mod_rewrite to deny access to *.php files by rewriting those requests and sending a F|forbidden flag:

RewriteEngine On
RewriteRule ^.*.php$ - [F,L]

Why did I start this article with

Preferably and in my opinion without the use of a security plugin

Because most security plugins are easy to defeat, especially once you have access to the file system the website resides on (e.g WordPress admin, FTP access, and so on). The post Defeating WordPress Security Plugins (Revisited) by @TheXC3LL has some nice red teaming thoughts about this.

Jan Reilink

My name is Jan. I am not a hacker, coder, developer, programmer or guru. I am merely a system administrator, doing my daily thing at Vevida in the Netherlands. With over 15 years of experience, my specialties include Windows Server, IIS, Linux (CentOS, Debian), security, PHP, WordPress, websites & optimization. Want to support me and donate? Use this link: https://paypal.me/jreilink.

Hi! Join the discussion, leave a reply!