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.
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 supercacheAllowOverride 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 .pkForceType text/plain
Fix Trackback issues
# trackback fixes RedirectMatch 301 (?i)^(.+)/trackback/?.*$ https://www.askapache.com$1
Secure WP Document_Root
Block Logins with empty User Agent
RewriteCond %{THE_REQUEST} ^POST.*wp-login [NC] RewriteCond %{HTTP_USER_AGENT} ^$ RewriteRule .* - [F]
Block Logins with bad cookie
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]
Comments