getButterfly
Resume

NAVIGATION

ATTRIBUTION

getButterfly
Dublin, Ireland

All Content Copyright ©2019
getButterfly

Do You Really Need Wordfence (Apache Edition)

Nope!

What you need is an up-to-date WordPress, up-to-date plugins, the latest server software, a bit of common sense and a set of rules for your .htaccess file.

See below for common sense:

  • HTTPS
  • HSTS
  • Remove the following usernames (if they exist): adminadministratortestroot
  • Regenerate wp-config.php security keys and salts
  • Disable file editing by adding define('DISALLOW_FILE_EDIT', true); in wp-config.php
  • Remove all default WordPress themes and only keep your active one
  • Remove unused plugins and only keep your active ones
  • Update your plugins
  • Change file permissions to 755

And see below for the Apache rules:

# WPD WordPress Firewall

# Disable display of directory contents
Options All -Indexes
IndexIgnore *

# Remove server information
ServerSignature Off

# Enabling tracking of symbolic links
Options +FollowSymLinks

# Rewrite any session cookies to make them more secure
# Make sure ALL cookies created by this server are HttpOnly and Secure
Header always edit Set-Cookie (.*) "$1;HttpOnly;Secure"

# Restrict login by IP
<Files wp-login.php>
    Order deny,allow
    Deny from all
    Allow from xxx.xxx.xxx.xxx
    Allow from xxx.xxx.xxx.xxx
    Allow from xxx.xxx.xxx.xxx
</Files>

# Protect wp-config.php
<Files wp-config.php>
    Order allow,deny
    Deny from all
</Files>

# Protect .htaccess and .htpasswds
<Files ~ "^.*\.([Hh][Tt][AaPp])">
    Order allow,deny
    Deny from all
</Files>

<Files admin-ajax.php>
    Order allow,deny
    Allow from all
    Satisfy any
</Files>

# Avoid comment spam and login spam for no referer or no user agent
# Replace example.com with your domain name
<IfModule mod_rewrite.c>
    RewriteCond %{REQUEST_METHOD} POST
    RewriteCond %{REQUEST_URI} .*/(wp-comments-post|wp-login)\.php.*
    RewriteCond %{HTTP_REFERER} !.example.com.* [OR]
    RewriteCond %{HTTP_USER_AGENT} ^$
    RewriteRule (.*) ^https://%{REMOTE_ADDR}/$ [R=301,L]
</IfModule>

# Block unauthorised usage of WordPress files
RewriteEngine On
RewriteBase /
RewriteRule ^wp-admin/includes/ - [F,L]
RewriteRule !^wp-includes/ - [S=3]
RewriteRule ^wp-includes/[^/]+\.php$ - [F,L]
RewriteRule ^wp-includes/js/tinymce/langs/.+\.php - [F,L]
RewriteRule ^wp-includes/theme-compat/ - [F,L]

# Protect against file injections
RewriteCond %{REQUEST_METHOD} GET
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=http:// [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=(\.\.//?)+ [OR]
RewriteCond %{QUERY_STRING} [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ [NC]
RewriteRule .* - [F]

# Various protections (XSS, clickjacking and MIME-Type sniffing)
<ifModule mod_headers.c>
    Header unset Server
    Header always unset X-Powered-By
    Header unset X-Powered-By
    Header unset X-CF-Powered-By
    Header unset X-Pingback
    Header unset X-Mod-Pagespeed

    Header always unset x-ua-compatible

    <FilesMatch "\.(html|php)$">
        Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
        Header always set X-Content-Type-Options "nosniff"
        Header always set X-XSS-Protection "1; mode=block"
        Header always set X-Frame-Options "SAMEORIGIN"
    </FilesMatch>
</ifModule>

# Block access on pattern detection
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{QUERY_STRING} (eval\() [NC,OR]
    RewriteCond %{QUERY_STRING} (127\.0\.0\.1) [NC,OR]
    RewriteCond %{QUERY_STRING} ([a-z0-9]{2000}) [NC,OR]
    RewriteCond %{QUERY_STRING} (javascript:)(.*)(;) [NC,OR]
    RewriteCond %{QUERY_STRING} (base64_encode)(.*)(\() [NC,OR]
    RewriteCond %{QUERY_STRING} (GLOBALS|REQUEST)(=|\[|%) [NC,OR]
    RewriteCond %{QUERY_STRING} (<|%3C)(.*)script(.*)(>|%3) [NC,OR]
    RewriteCond %{QUERY_STRING} (\\|\.\.\.|\.\./|~|`|<|>|\|) [NC,OR]
    RewriteCond %{QUERY_STRING} (boot\.ini|etc/passwd|self/environ) [NC,OR]
    RewriteCond %{QUERY_STRING} (thumbs?(_editor|open)?|tim(thumb)?)\.php [NC,OR]
    RewriteCond %{QUERY_STRING} (\'|\")(.*)(drop|insert|md5|select|union) [NC]
    RewriteRule .* - [F]
</IfModule>

# Block access on request method detection
<IfModule mod_rewrite.c>
    RewriteCond %{REQUEST_METHOD} ^(connect|debug|delete|move|put|trace|track) [NC]
    RewriteRule .* - [F]
</IfModule>

# Block access on referer detection
<IfModule mod_rewrite.c>
    RewriteCond %{HTTP_REFERER} ([a-z0-9]{2000}) [NC,OR]
    RewriteCond %{HTTP_REFERER} (semalt.com|malicioushost.com) [NC]
    RewriteRule .* - [F]
</IfModule>

# Block access on connection detection
<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteCond %{HTTP:VIA} !^$ [OR]
    RewriteCond %{HTTP:FORWARDED} !^$ [OR]
    RewriteCond %{HTTP:USERAGENT_VIA} !^$ [OR]
    RewriteCond %{HTTP:X_FORWARDED_FOR} !^$ [OR]
    RewriteCond %{HTTP:PROXY_CONNECTION} !^$ [OR]
    RewriteCond %{HTTP:XPROXY_CONNECTION} !^$ [OR]
    RewriteCond %{HTTP:HTTP_PC_REMOTE_ADDR} !^$ [OR]
    RewriteCond %{HTTP:HTTP_CLIENT_IP} !^$
    RewriteRule ^(.*)$ - [F]
</IfModule>

# Block access on request string detection
<IfModule mod_alias.c>
    RedirectMatch 403 (?i)([a-z0-9]{2000})
    RedirectMatch 403 (?i)(https?|ftp|php):/
    RedirectMatch 403 (?i)(base64_encode)(.*)(\()
    RedirectMatch 403 (?i)(=\\\'|=\\%27|/\\\'/?)\.
    RedirectMatch 403 (?i)/(\$(\&)?|\*|\"|\.|,|&|&?)/?$
    RedirectMatch 403 (?i)(\{0\}|\(/\(|\.\.\.|\+\+\+|\\\"\\\")
    RedirectMatch 403 (?i)(~|`|<|>|:|;|,|%|\\|\s|\{|\}|\[|\]|\|)
    RedirectMatch 403 (?i)/(=|\$&|_mm|cgi-|etc/passwd|muieblack)
    RedirectMatch 403 (?i)(&pws=0|_vti_|\(null\)|\{\$itemURL\}|echo(.*)kae|etc/passwd|eval\(|self/environ)
    RedirectMatch 403 (?i)\.(aspx?|bash|bak?|cfg|cgi|dll|exe|git|hg|ini|jsp|log|mdb|out|sql|svn|swp|tar|rar|rdf)$
    RedirectMatch 403 (?i)/(^$|(wp-)?config|mobiquo|phpinfo|shell|sqlpatch|thumb|thumb_editor|thumbopen|timthumb|webshell)\.php
</IfModule>

# Block access on user agent detection
<IfModule mod_setenvif.c>
    SetEnvIfNoCase User-Agent ([a-z0-9]{2000}) bad_bot
    SetEnvIfNoCase User-Agent (archive.org|binlar|casper|checkpriv|choppy|clshttp|cmsworld|diavol|dotbot|extract|feedfinder|flicky|g00g1e|harvest|heritrix|httrack|kmccrew|loader|miner|nikto|nutch|planetwork|postrank|purebot|pycurl|python|seekerspider|siclab|skygrid|sqlmap|sucker|turnit|vikspider|winhttp|xxxyy|youda|zmeu|zune) bad_bot

    <limit GET POST PUT>
        Order Allow,Deny
        Allow from All
        Deny from env=bad_bot
    </limit>
</IfModule>

And that’s it, you can remove Wordfence and enjoy a fast and secure website. Note that you will need to amend some of the sections such as potentially malicious hosts or IP addresses to ban.



My Battle Tested Recommendations

Jetpack
Dreamhost
WordPress.com
CodeCanyon
SEMrush

Disclaimer: These recommendations contain affiliate links.