Skip to content

Instantly share code, notes, and snippets.

@sonnetmia
Last active June 10, 2020 15:44
Show Gist options
  • Save sonnetmia/b5dbc24660067e71e0e0 to your computer and use it in GitHub Desktop.
Save sonnetmia/b5dbc24660067e71e0e0 to your computer and use it in GitHub Desktop.
WordPress htaccess security imporvement
###########################
# WP htaccess Boilerplate #
#Slightly modified to improve hardening#
###########################
### https://github.com/Creare/WP-htaccess/
############
# Security #
############
### Recognise SSL when set at a load balancer/proxy level (for CloudFlare)
SetEnvIf X-Forwarded-Proto https HTTPS=on
### Prevent wp-config.php from being loaded:
<files wp-config.php>
order allow,deny
deny from all
</files>
### Prevent sftp-config.json from being loaded:
<files sftp-config.json>
order allow,deny
deny from all
</files>
### Protect .htaccess
<Files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</Files>
### Prevent this .htaccess from being accessed:
<files .htaccess>
order allow,deny
deny from all
</files>
### Prevent WordPress' readme.html from being accessed (as it contains the version number)
<files readme.html>
Deny from all
</files>
<files readme.txt>
Order allow,deny
Deny from all
</files>
<files install.php>
Order allow,deny
Deny from all
</files>
<Files debug.log>
Order allow,deny
Deny from all
</Files>
<IfModule mod_headers.c>
Header set X-XSS-Protection "1; mode=block"
Header always append X-Frame-Options SAMEORIGIN
Header set X-Content-Type-Options nosniff
</IfModule>
### Secure wp-includes
<IfModule mod_rewrite.c>
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]
# Rules to prevent php execution in uploads
RewriteRule ^(.*)/uploads/(.*).php(.?) - [F]
### SQL Injection Protection
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,OR]
RewriteCond %{QUERY_STRING} \=PHP[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12} [NC,OR]
RewriteCond %{QUERY_STRING} (\.\./|\.\.) [OR]
RewriteCond %{QUERY_STRING} ftp\: [NC,OR]
RewriteCond %{QUERY_STRING} http\: [NC,OR]
RewriteCond %{QUERY_STRING} https\: [NC,OR]
RewriteCond %{QUERY_STRING} \=\|w\| [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)/self/(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} ^(.*)cPath=http://(.*)$ [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^s]*s)+cript.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*iframe.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} (<|%3C)([^i]*i)+frame.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
RewriteCond %{QUERY_STRING} base64_(en|de)code[^(]*\([^)]*\) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)|<|>).* [NC,OR]
RewriteCond %{QUERY_STRING} (NULL|OUTFILE|LOAD_FILE) [OR]
RewriteCond %{QUERY_STRING} (\./|\../|\.../)+(motd|etc|bin) [NC,OR]
RewriteCond %{QUERY_STRING} (localhost|loopback|127\.0\.0\.1) [NC,OR]
RewriteCond %{QUERY_STRING} (<|>|'|%0A|%0D|%27|%3C|%3E|%00) [NC,OR]
RewriteCond %{QUERY_STRING} concat[^\(]*\( [NC,OR]
RewriteCond %{QUERY_STRING} union([^s]*s)+elect [NC,OR]
RewriteCond %{QUERY_STRING} union([^a]*a)+ll([^s]*s)+elect [NC,OR]
RewriteCond %{QUERY_STRING} (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode) [NC,OR]
RewriteCond %{QUERY_STRING} (sp_executesql) [NC]
RewriteCond %{QUERY_STRING} !^loggedout=true
RewriteCond %{QUERY_STRING} !^action=rp
RewriteCond %{HTTP_COOKIE} !^.*wordpress_logged_in_.*$
RewriteCond %{HTTP_REFERER} !^http://maps\.googleapis\.com(.*)$
RewriteRule ^(.*)$ index.php [F,L]
### End SQL Injection Protection
# Rules to block foreign characters in URLs
RewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%E|%F).* [NC]
RewriteRule ^(.*)$ - [F]
# Rules to help reduce spam
# Change website.com to your domain name
RewriteCond %{REQUEST_METHOD} POST
RewriteCond %{REQUEST_URI} ^(.*)wp-comments-post\.php*
RewriteCond %{HTTP_REFERER} !^(.*)website.com.*
RewriteCond %{HTTP_REFERER} !^http://jetpack\.wordpress\.com/jetpack-comment/ [OR]
RewriteCond %{HTTP_USER_AGENT} ^$
RewriteRule ^(.*)$ - [F]
</IfModule>
### Prevent directory browsing
<IfModule mod_autoindex.c>
Options -Indexes
# deny folder listing
IndexIgnore *
</IfModule>
### Disable HTTP Trace
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^(TRACE|DELETE|TRACK) [NC]
RewriteRule .* - [F]
### Block access to hidden files & directories
<IfModule mod_rewrite.c>
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule "(^|/)\." - [F]
</IfModule>
### Block access to source files
<FilesMatch "(^#.*#|\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|sw[op])|~)$">
Order allow,deny
Deny from all
Satisfy All
</FilesMatch>
###############################
# Additional Rewrite Settings #
###############################
# Option 1
# http://domain > http://www.domain
<IfModule mod_rewrite.c>
# Options +FollowSymlinks #Not supported by some hosting
### If you wish to redirect to a https:// simply substitute http: with https:
RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
### Redirect away from /index.php to clear path
RewriteCond %{THE_REQUEST} ^.*/index.php
RewriteRule ^(.*)index.php$ http://www.%{HTTP_HOST}%{REQUEST_URI}$1 [R=301,L]
</IfModule>
# Option 2
# http://www.domain > http://domain
#<IfModule mod_rewrite.c>
# Options +FollowSymlinks #Not supported by some hosting
### If you wish to redirect to a https:// simply substitute http: with https:
#RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
#RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
### Redirect away from /index.php to clear path
#RewriteCond %{THE_REQUEST} ^.*/index.php
#RewriteRule ^(.*)index.php$ http://%{HTTP_HOST}%{REQUEST_URI}$1 [R=301,L]
#</IfModule>
##############################
# Default Wordpress Settings #
##############################
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
#######################
# Speed & Compression #
#######################
# BEGIN Expire headers
<ifModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 5 seconds"
ExpiresByType image/x-icon "access plus 2592000 seconds"
ExpiresByType image/jpeg "access plus 2592000 seconds"
ExpiresByType image/png "access plus 2592000 seconds"
ExpiresByType image/gif "access plus 2592000 seconds"
ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
ExpiresByType text/css "access plus 604800 seconds"
ExpiresByType text/javascript "access plus 216000 seconds"
ExpiresByType application/javascript "access plus 216000 seconds"
ExpiresByType application/x-javascript "access plus 216000 seconds"
ExpiresByType text/html "access plus 600 seconds"
ExpiresByType application/xhtml+xml "access plus 600 seconds"
</ifModule>
# END Expire headers
<ifModule mod_headers.c>
# BEGIN Cache-Control Headers
<filesMatch "\.(ico|jpe?g|png|gif|swf)$">
Header set Cache-Control "public"
</filesMatch>
<filesMatch "\.(css)$">
Header set Cache-Control "public"
</filesMatch>
<filesMatch "\.(js)$">
Header set Cache-Control "private"
</filesMatch>
<filesMatch "\.(x?html?|php)$">
Header set Cache-Control "private, must-revalidate"
</filesMatch>
# END Cache-Control Headers
</ifModule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/xhtml text/html text/plain text/xml text/javascript application/x-javascript text/css
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
Header append Vary User-Agent env=!dont-vary
</IfModule>
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE application/x-javascript
#Remove the ETag header
Header unset ETag
FileETag None
#######################
# File Format Support #
#######################
### Add support for SVG and HTC
AddType image/svg+xml svg svgz
AddEncoding gzip svgz
AddType text/x-component .htc
########################
# Manual 301 Redirects #
########################
#redirect 301 /old-page-url.html https://www.domain.co.uk/new-page-url
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment