Some of the security issues commonly seen on a website can be taken care of using the .htaccess (hypertext access) file. In this article, I am gonna be showing the .htaccess configuration from my WordPress website and explain the security issues sorted out using it. However, before we get into that, let’s look into what an .htaccess file actually is.
.htaccess is a configuration file for use on web servers running the Apache Web Server software. When a .htaccess file is placed in a directory which is in turn ‘loaded via the Apache Web Server’, then the .htaccess file is detected and executed by the Apache Web Server software.
— HTACCESS-Guide
These .htaccess files can be used to alter the configuration of the Apache Web Server software to enable/disable additional functionality and features that the Apache Web Server software has to offer. These facilities include basic redirect functionality, for instance if a ‘404 file not found’ error occurs, or for more advanced functions such as content password protection or image hot link prevention.
WARNING
- The .htaccess file is a server configuration file. Even a typo can cause your server to be misconfigured resulting in your website going down! Please note that the author will not be held responsible for any mistakes you make that cause problems on your server.
- If you do not know what you are doing, consult with a web developer. If you are feeling adventurous, be sure to make backups of your original .htaccess file and proceed with caution.
- If the site does go down, please use your FTP/SSH/cPanel access to restore the .htaccess file from the backup.
- While the .htaccess configuration on my server is tailored towards securing my WordPress installation, many of the directives given below can be modified (if required) and used according to your non-WordPress website’s setup. However, I highly recommend that any such modification be made with caution and after taking a proper backup.
Now then, let’s dive into the .htaccess file block by block and see how it helps me secure my website. Any of the following code blocks which you would like to use on your own server needs to be copied to the .htaccess file in your website root. As mentioned above, please take a backup of your .htaccess file before making any changes.
Protecting the HTACCESS file
Considering how important the .htaccess file is, it is crucial to protect the file itself from unauthorized users. The following block of code does just that.
# Protect HTACCESS
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</files>
Protecting Other Important Files
The following block of code can be used to protect other important files in WordPress such as error logs, wp-config.php, and php.ini.
# Protect Important Files
<FilesMatch "^.*(error_log|wp-config\.php|php.ini)$">
Order deny,allow
Deny from all
</FilesMatch>
Disable Hotlinking of Images
Image hotlinking can result in the slowing down of your website. If a person embeds images from your website on their own site, every time the image is viewed on their site, it gets loaded from your server. As a result, your bandwidth gets consumed without them even visiting your site.
Use the following block of code to prevent this from happening. Make sure to replace “jinsonvarghese.com” with your domain.
# Disable hotlinking of images with forbidden or custom image option
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?jinsonvarghese.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?google.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ – [NC,F,L]
Check it yourself:
Check if your images are being hotlinked by searching the following in Google. What the following Google dork will do is search for every image from your website but it removes every result that includes your own URL. The remaining search results will show any site where your images are hotlinked.
inurl:yourwebsite.com -site:yourwebsite.com
Disable HTTP TRACE Method
The HTTP TRACE method is designed for diagnostic purposes. If enabled, the web server will respond to requests that use the TRACE method by echoing in its response the exact request that was received.
— PortSwigger
This behavior is often harmless, but occasionally leads to the disclosure of sensitive information such as internal authentication headers appended by reverse proxies. This functionality could historically be used to bypass the HttpOnly cookie flag on cookies, but this is no longer possible in modern web browsers.
Use the following block of code to disable HTTP TRACE method on your server.
# Disable HTTP TRACE Method
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRACE
RewriteRule .* - [F]
</IfModule>
Disable Server Signature
Server signature can reveal sensitive information such the version of the software components used to an attacker, who will be able to better prepare their attacks based on this information. They are usually revealed in server responses, 404 error pages, directory listing, etc.
Server signature can be disabled by adding the following directive in the .htaccess file.
# Disable server signature
ServerSignature Off
Enable HTTP Security Headers
HTTP security headers can be used to provide yet another layer of security in order to help mitigate security vulnerabilities.
X-XSS-Protection Header
The X-XSS-Protection header is designed to enable the cross-site scripting (XSS) filter built into modern web browsers.
— keyCDN
The following block of code sets the X-XSS-Protection header.
# Enable X-XSS-Protection Header
<IfModule mod_headers.c>
Header set X-XSS-Protection "1; mode=block"
</IfModule>
Reference:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection
X-Content-Type-Options Header
The X-Content-Type-Options header prevents Internet Explorer and Google Chrome from sniffing a response away from the declared Content-Type. This helps reduce the danger of drive-by downloads and helps treat the content the right way.
— keyCDN
The following block of code sets the X-Content-Type-Options header.
# Enable X-Content-Type Header
<IfModule mod_headers.c>
Header set X-Content-Type-Options nosniff
</IfModule>
Reference:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
HTTP Strict Transport Security (HSTS) Header
HTTP Strict Transport Security (HSTS) is a security enhancement that restricts web browsers to access web servers solely over HTTPS. This ensures the connection cannot be establish through an insecure HTTP connection which could be susceptible to attacks. HSTS is defined in the response header as Strict-Transport-Security and once the supported browser receives that header it knows to deliver all information over HTTPS.
— keyCDN
The following block of code sets the Strict Transport Security header.
# Enable Strict Transport Security Header
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains"
</IfModule>
Reference:
For more information on the HSTS Header and its directives to choose from according to your specific requirement, please refer to https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
X-Frame-Options Header
Clickjacking (User Interface redress attack, UI redress attack, UI redressing) is a malicious technique of tricking a Web user into clicking on something different from what the user perceives they are clicking on, thus potentially revealing confidential information or taking control of their computer while clicking on seemingly innocuous web pages.
— Acunetix
The X-Frame-Options HTTP header remains the most commonly supported clickjacking protection option.
The following block of code sets the X-Frame-Options header.
# Enable X-Frame-Options Header
<IfModule mod_headers.c>
Header set X-Frame-Options "SAMEORIGIN"
</IfModule>
Reference:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
Referrer-Policy Header
Added to your site’s .htaccess file or server configuration file, this code instructs supportive browsers to only set the referrer header for request from the current domain (same-origin). Keep in mind that this header is less about security and more about controlling referrer information, as is required by various rules and regulations (e.g., GDPR).
— htaccessbook
The following block of code sets the Referrer-Policy header.
# Enable Referrer-Policy Header
<IfModule mod_headers.c>
Header set Referrer-Policy "same-origin"
</IfModule>
Reference:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
Disable Directory Listing
When directory listing is enabled, an attacker could make a request to www.example.com/admin/, the response from the server would include the directory content of the directory admin.
To prevent unauthorized access to your website directories, add the following line of code to your .htaccess file.
# Disable Directory Listing
Options All -Indexes
Protection Against WordPress Script Injection Attacks
Attackers inject malicious code into the website code to perform malicious actions such as getting unauthorized access to sensitive data. The following block of code can protect WordPress websites from such attacks.
# Protect Against Script Injection
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} GLOBALS(=|[|%[0-9A-Z]{0,2}) [OR]
RewriteCond %{QUERY_STRING} _REQUEST(=|[|%[0-9A-Z]{0,2})
RewriteRule ^(.*)$ index.php [F,L]
Protection Against SQL Injection Attacks
While this does not offer complete protection against SQL Injection attacks or block more complex attacks like a WAF would do, the following block of code can be at least used to stop some of the most commonly seen SQLi attacks.
# Protect Against SQL Injection
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_METHOD} ^(HEAD|TRACE|DELETE|TRACK) [NC]
RewriteRule ^(.*)$ - [F,L]
RewriteCond %{QUERY_STRING} \.\.\/ [NC,OR]
RewriteCond %{QUERY_STRING} boot\.ini [NC,OR]
RewriteCond %{QUERY_STRING} tag\= [NC,OR]
RewriteCond %{QUERY_STRING} ftp\: [NC,OR]
RewriteCond %{QUERY_STRING} http\: [NC,OR]
RewriteCond %{QUERY_STRING} https\: [NC,OR]
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|%3D) [NC,OR]
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(\[|\]|\(|\)|<|>|ê|"|;|\?|\*|=$).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(%24&x).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%E|%F|127\.0).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(globals|encode|localhost|loopback).* [NC,OR]
RewriteCond %{QUERY_STRING} ^.*(request|select|insert|union|declare).* [NC]
RewriteCond %{HTTP_COOKIE} !^.*WordPress_logged_in_.*$
RewriteRule ^(.*)$ - [F,L]
</IfModule>
Block Author Scans in WordPress
If permalinks are enabled, in many WordPress installations it is possible to enumerate all the WordPress usernames iterating through the author archives. Whenever a post is published, the username or alias is shown as the author. For example, the URL http://site.com/?author=1 will show all the posts from user id 1. Attackers can abuse this functionality to figure out which usernames are available on the site.
— Acunetix
Adding the below code to the .htaccess file in your WordPress website‘s root directory will block all author scan attacks.
# BEGIN block author scans
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} (author=\d+) [NC]
RewriteRule .* - [F]
# END block author scans
Block DoS Attacks on load-scripts.php in WordPress
The load-scripts.php file in WordPress accepts a load parameter which can be provided with a lot of JavaScript filenames and in return, the PHP file in question will concatenate the JavaScript files and return them all together in one go.
It is possible for attackers to exploit this function and send a large number of requests, in order to bring a website down.
The following block of code will make sure that all attempts to access the load-scripts.php file will return a 403 Forbidden error, unless originated from your domain. Make sure to replace “jinsonvarghese\.com” with your domain.
# Prevent DOS Attacks on load-scripts.php
RewriteCond %{HTTP_REFERER} !jinsonvarghese\.com [NC]
RewriteCond %{THE_REQUEST} \.php[\ /?].*HTTP/ [NC]
RewriteRule ^wp-admin/load-scripts\.php$ – [R=403,L]
Test It Yourself:
Once the code has been added and the .htaccess file has been saved, visit yourdomain.com/wp-admin/load-scripts.php.
Hide WordPress Files From Unauthorized Users
After a new WordPress installation, there are some files (which are not much of a security risk) that remain accessible to users. Since I don’t like the idea of unauthorized users being able to access these files, I use the following code to hide them. The files in question are /wp-admin/install.php, /wp-admin/upgrade.php, readme.html and license.txt.
# Redirect install.php
RedirectMatch Permanent wp-admin/install(-helper)?\.php /
RedirectMatch Permanent wp-admin/upgrade\.php /
# Protect Files
<Files "readme.html">
Require all denied
</Files>
<Files "license.txt">
Require all denied
</Files>
Block WordPress XML-RPC Requests
The WordPress XML-RPC is a specification that aims to standardize communications between different systems. It uses HTTP as the transport mechanism and XML as encoding mechanism which allows for a wide range of data to be transmitted.
— Kinsta
In the recent years, XML-RPC has become an increasingly large target for brute force attacks. When using XML-RPC to make calls, you need to supply a username and password and the system will confirm when you hit a valid pair.
If you are not using a web application firewall like Astra or a WordPress plugin like WP Hardening to block attacks on your WordPress site’s XML-RPC, you can manually set it up to block such attacks by adding the following block of code to your .htaccess file.
# Block WordPress xmlrpc.php requests
<Files xmlrpc.php>
order deny,allow
deny from all
allow from xxx.xxx.xxx.xxx
allow from xxx.xxx.xxx.xxx
</Files>
In the above code, we are instructing the server to block all access to xmlrpc.php except for the ones originating from the IP address specified after “allow from”.
Final Thoughts
These are some of the security measures I have used in my own .htaccess file. During my day job as an Information Security Analyst, I come across multiple sites that are not properly configured and could use these simple fixes.
I decided to post this article knowing that there are many more websites out there that could use these fixes to be better secured. Hope it helped! 🙂
Thanks very useful for me:)
Glad to hear that. 🙂