WordPress
Some WordPress security and other fun facts.
Improving WordPress security with .htaccess
In this article I’ll share some of the security tweaks I tend to add to the .htaccess to improve security of the WordPress-installation.
Hide the wp-config.php file
Since the wp-config.php file contains our database credentials, we do not want this file to be accessible, PERIOD. So by adding this snippet to our .htaccess file we can prevent access to it:
#hide wp-config file
order allow,deny
deny from all
This rule will prevent that the wp-config.php is accessible.
Hide the .htaccess file itself
Preventing abuse by adding rules to our .htaccess is only useful if the .htaccess can’t be compromised itself.
To make sure that doesn’t happen we can add this to the .htaccess file:
#hide htaccess file
order allow,deny
deny from all
Block requests towards the wp-includes folder and files
This is in fact a no-brainer. No legitimate request will ever go towards the wp-includes folder or the files in that folder. On the other hand it’s a popular spot to hide malicious files, such as backdoors and shells.
So let’s make sure this folder and its content isn’t accessible. We can do this by adding this little snippet to our .htaccess:
# Block wp-includes folder and 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]
Blocking the TRACE method
Blocking the TRACE method will help to counteract XSS (Cross Site Scripting) attacks.
# Block trace method
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]
Prevent username enumeration
Within the url structure of WordPress, it’s (in some situations) easy to ascertain the usernames of the authors. This could be done by using following url string:
https://domain.com/?author=1
https://domain.com/?author=2
...
This will then result in a url similar to this:
https://domain.com/author/mysupersecretusername/
You immediately understand this can be used to ascertain a list of usernames, which can then be used for a brute forcing attack.
We can stop this by adding this snippet to our .htaccess file:
#Stop username enumeration
RewriteCond %{REQUEST_URI} !^/wp-admin [NC]
RewriteCond %{QUERY_STRING} author=\d
RewriteRule ^ /? [L,R=301]
Useful common 301 redirect .htaccess rules.
There are a few common .htaccess 301 redirect rules that are very useful and that I find myself searching for each time I build a website.
What is an .htaccess file?
The .htaccess, or Hypertext Access file, is a configuration text file that controls the directory, as well as any subdirectories, where it is located on an Apache web server. If you use a Linux-based web hosting plan, your web properties likely run on Apache. You may have seen the .htaccess file in certain directories, particularly if you have deployed WordPress, Joomla, Drupal or any other content management web software. The .htaccess file can include specific instructions to the server. This file can configure the server to require a password for the directory where it resides. The .htaccess file can also be configured to automatically redirect users to another index file or site, restrict or allow users based on IP addresses, and disable directory listings. You may never need to edit the .htaccess file, but if you do, you must make sure that the file is named ‘.htaccess’ only, with the period in front and no .txt or .htm file extension.
How do you redirect a single page?
Redirect 301 /pagename.php http://www.domain.com/pagename.html
How do you redirect an entire site or domain to a new one?
Redirect 301 / http://www.domain.com/
How do you redirect an entire site to a sub folder?
Redirect 301 / http://www.domain.com/subfolder/
How do you redirect a sub folder to different website?
Redirect 301 /subfolder http://www.domain.com/
Speedup WordPress with .htaccess, the code.
Add the code below to your .htaccess file.
# BEGIN SPEEDUP
<FilesMatch "\.(html|php|txt|xml|js|css)$">
SetOutputFilter DEFLATE
# BEGIN Cache-Control Headers
<filesMatch "\.(ico|jpeg|jpg|png|gif|swf|pdf|svg|js|flv)$">
Header set Cache-Control "max-age=84600, public"
# END Cache-Control Headers
# BEGIN Expire headers
ExpiresActive On
# Images
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
# Video
ExpiresByType video/mp4 "access plus 1 year"
ExpiresByType video/mpeg "access plus 1 year"
# CSS, JavaScript
ExpiresByType text/css "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
# Others
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType application/x-shockwave-flash "access plus 1 month"
# END Expire headers
# START DEFLATE COMPRESSION
AddOutputFilterByType DEFLATE "application/atom+xml" \
"application/javascript" \
"application/json" \
"application/ld+json" \
"application/manifest+json" \
"application/rdf+xml" \
"application/rss+xml" \
"application/schema+json" \
"application/vnd.geo+json" \
"application/vnd.ms-fontobject" \
"application/x-font" \
"application/x-font-opentype" \
"application/x-font-otf" \
"application/x-font-truetype" \
"application/x-font-ttf" \
"application/x-javascript" \
"application/x-web-app-manifest+json" \
"application/xhtml+xml" \
"application/xml" \
"font/eot" \
"font/otf" \
"font/ttf" \
"font/opentype" \
"image/bmp" \
"image/svg+xml" \
"image/vnd.microsoft.icon" \
"image/x-icon" \
"text/cache-manifest" \
"text/css" \
"text/html" \
"text/javascript" \
"text/plain" \
"text/vcard" \
"text/vnd.rim.location.xloc" \
"text/vtt" \
"text/x-component" \
"text/x-cross-domain-policy" \
"text/xml"
# DEFLATE COMPRESSION
# 480 weeks
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)$">
Header set Cache-Control "max-age=290304000, public"
# END SPEEDUP
Securing WordPress with .htaccess, the code.
Add the security code below to your .htaccess file.
# BEGIN SECURITY
#hide wp-config file
order allow,deny
deny from all
#hide htaccess file
order allow,deny
deny from all
# Block wp-includes folder and 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]
# Block trace method
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]
# END SECURITY