Do You Really Need Wordfence (Apache Edition)

on in Blog
Last modified on

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.

Related posts