Stopping WordPress Exploits and Spam

Here's how to block the most common wordpress exploits and spam to secure your site and server.

Die 99% of WP Malware

There are couple WP core files that you can modify to make it impossible for an attacker to exploit. It is simply by adding a die(); to the top of the at-risk files. 0wn-wp-explits

Add a die(); as the very first php line to run (after ) in the following files:

  • wp-links-opml.php
  • wp-comments-post.php
  • wp-trackback.php

When to die

wp-links-opml.php - can be disabled when the site is NOT using the Links feature in the backend.

wp-comments-post.php - can be disabled when the site is not using WP comments, such as Disqus.

wp-trackback.php - can be disabled if you aren't using trackbacks.

Secure xmlrpc.php

Unless you have a literal reason for keeping xmlrpc.php (such as if you rely on pings or trackbacks or 3rd-party tools for editors) this file should be blocked as it can be used for brute-force login attempts.

Order Deny,Allow
Deny from All
Allow from localhost
Satisfy All

Block obvious Spam

The best way to create targeted .htaccess rules for blocking spam is to add a logging statement to the php files like comments.php in order to see the HTTP headers and request needed for designing specific blocks against them.

Posts to /wp-login.php that are using HTTP Protocol version 1.0 (not 1.1) are essentially almost always spam unless your server is acting as an origin for some proxying cache like an F5, varnish, etc.

RewriteCond %{THE_REQUEST} ^POST\ /wp-login.php\ HTTP/1\.0 [NC]
RewriteRule .* - [F]

RewriteCond %{THE_REQUEST} !^(POST|GET|HEAD|PROPFIND|OPTIONS)\ .+\ HTTP/(0\.9|1\.0|1\.1) [NC,OR]
RewriteRule .* - [F]

RewriteCond %{HTTP_COOKIE} ^$

Secure WP Super Cache

I have actually moved to batcache/memcache, but for WP Super Cache you need to secure that directory to prevent malicious scripts/code from being cached to your disk and then exec'd by the malicous 3rd party. Disallowing .htaccess files in this uploads dir is also a big performance gain in terms of inode/file lookups.

# faster supercache

AllowOverride none

Secure WordPress Uploads Folder

Stick in your WP /wp-content/uploads/.htaccess file. Many of the most impactful exploits target plugins such as Gravity Forms that can allow an attacker to upload a malicious image or file that may contain php code or exploit code within its binary, and cause a RCE. Almost all of the Gravity Form plugins exploits take advantage of it by uploading malformed and malicous php files into the sites uploads folder. Then the attacker simply requests that uploaded malicous file to trigger it. The solution is to deny any files in the uploads folder from using any cgi.

Basically, need to remove any handlers for files in the uploads folder so that its impossible for any interpreter like bash, python, ruby, etc., to run an uploaded file, instead the are forced to be treated as octet-streams which is what they always should be anyways.

Note that for certain file extensions I am forcing them to be interpreted by Apache as plain text. This means no interpreters are even contemplated for use in opening an upload file.

# faster and safer uploads
RemoveHandler .ini .sh .bsh .bash .awk .nawk .gawk .csh .var .c .in .h .asc .md5 .sha .sha1 .cgi .pl .php .inc .asp .exe .bin .py .pl .phtml
RemoveHandler .out .output .overlay .p12 .p5c .pam .pas .patch .phps .php5 .php4 .php3 .pbxproj .pdb .pdf .pem .perl .phar .php .php_cs .phpize .phpt .pingpong .pipelining .pk

ForceType text/plain

Fix Trackback issues

# trackback fixes
RedirectMatch 301 (?i)^(.+)/trackback/?.*$$1

Secure WP Document_Root

Block Logins with empty User Agent

RewriteCond %{THE_REQUEST} ^POST.*wp-login [NC]
RewriteCond %{HTTP_USER_AGENT} ^$
RewriteRule .* - [F]

You should all be using a custom login cookie name definable with constants in your wp-config.php file. That means the default cookie wordpress_test_cookie will never be set, so you can block bots that use this default!

The way to deviate from the default is to set this constant to anything you want in your wp-config.php

define( 'TEST_COOKIE', 'use_this_cookie_name_instead_of_wordpress_test_cookie' );

Block bad test cookies

RewriteCond %{THE_REQUEST} ^POST.*wp-login [NC]
RewriteCond %{HTTP:Cookie} "wordpress_test_cookie=WP+Cookie+check" [NC]
RewriteRule .* - [F]'

Block revslider exploit requests

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ .*revslider_show_image.* [NC]
RewriteRule .* - [F,L]

RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ .*revslider_show_image.* [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* - [F,L]

Block bad HTTP Protocol and Request Methods

Blocks a request method other than GET, POST, HEAD, PROPFIND, and OPTIONS. Also blocks HTTP protocols other than /p0.9, 1.0, and 1.1

RewriteCond %{THE_REQUEST} !^(POST|GET|HEAD|PROPFIND|OPTIONS)\ .+\ HTTP/(0\.9|1\.0|1\.1) [NC,OR]
RewriteRule .* - [F,L]

Block empty Host Headers

A lot of bots will try to make requests against your site using IP's or bad hostnames. Here's how to block empty HOST header requests.

RewriteCond %{HTTP_HOST} ^$
RewriteRule .* - [F,L]

Hacking Htaccess PHP Security WordPress security spam wordpress wordpress exploits