Blocking Access to Non-Existing Themes in WordPress

Over the last few months I have been seeing a rise in automated exploit scans of the WordPress based sites I manage. So I have decided to squash this annoying exploit by writing an .htaccess directive.

The exploit scanner I was seeing across my managed sites were looking for a vulnerability in the followings directories and/or themes:


http://example.com/wp-content/themes/awake/lib/scripts/dl-skin.php
http://example.com/wp-content/themes/myriad/lib/scripts/dl-skin.php
http://example.com/wp-content/themes/modular/lib/scripts/dl-skin.php
http://example.com/wp-content/themes/construct/lib/scripts/dl-skin.php
http://example.com/wp-content/themes/dejavu/lib/scripts/dl-skin.php
http://example.com/wp-content/themes/method/lib/scripts/dl-skin.php
http://example.com/wp-content/themes/elegance/lib/scripts/dl-skin.php
http://example.com/wp-content/themes/fusion/lib/scripts/dl-skin.php
http://example.com/wp-content/themes/persuasion/lib/scripts/dl-skin.php
http://example.com/wp-content/themes/echelon/lib/scripts/dl-skin.php
http://example.com/wp-content/themes/infocus2/lib/scripts/dl-skin.php
http://example.com/wp-content/themes/infocus/lib/scripts/dl-skin.php
...

I know I could just write a redirect just to look for dl-skin.php, and called it a day. But instead, I didn’t want to revisit when the next exploit came knocking. So I created a directive that will drop any requests for all themes folders – except for the theme directory I declared – a whitelist of themes if you would.

I can do this, because I use a custom themes on these site and I also know what that theme’s folder name will be – usually something along the name of the site. So if you change your theme a lot or don’t know what your themes’ folder name is You May Not Want To Use This. This is meant for people using custom themes or sites that are managed by an Agency or Developer(s).

The Code

# Blocks requests to other themes with possible security holes
# Only Themes directory names starting with __ThemeNameHere__ are valid.
<IfModule mod_alias.c>
    RedirectMatch 403 (?i)(__subFolder__/)?wp-content/themes/(?!__ThemeNameHere__)
</IfModule>

How it Works?

This will only allow requests to http://example.com/__subFolder__/wp-content/themes/__ThemeNameHere__/* while return an HTTP/403 to any other folder in the Themes Directory. The __subFolder__ is optional – this is to allow for WordPress installs that are located in a sub-directory from the site root.

The Technical Explanation: Redirect to 403 If Match Regular Expression of (?i) Case Insensitivity, Capture Group of subFolder/ but is optional, followed by wp-content/themes/ then a negative (or negated) look ahead for ThemeNameHere that is a word (\w) and more (+).

How to Use It?

To implement this, place the code in your site’s .htaccess below the WordPress Section. Don’t forget to update the following variables:

__subFolder__  # The Sub Folder where your WordPress site lives
__ThemeNameHere__  # The Folder Name of your theme, could Be beginning or whole name

Example

Assuming your WordPress Site is in a folder named blog and you access it via http://example.com/blog/ and your theme is the default ‘TwentyFifteen’ Theme, which is stored in a folder name ‘twentyfifteen’, the code you would use would look like this:

<IfModule mod_alias.c>
    RedirectMatch 403 (?i)(blog)?wp-content/themes/(?!twentyfifteen) 
</IfModule>

If your WordPress site is stored in root of your site – http://example.com/ the code you would use is:

<IfModule mod_alias.c>
    RedirectMatch 403 (?i)wp-content/themes/(?!twentyfifteen)
</IfModule>

Try it out and Feedback

Have you seen this exploit scanner or another like it? Trying out this little redirect or having problems with it? Lets continue the discussion in the comments below…

Update – 2015-03-17: Dropped \w+ declaration after the theme name – this would not match requests with hyphens in then.