Last active
June 10, 2020 15:44
-
-
Save sonnetmia/b5dbc24660067e71e0e0 to your computer and use it in GitHub Desktop.
WordPress htaccess security imporvement
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
########################### | |
# 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