What’s on my .htaccess?

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.

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.

— HTACCESS-Guide

WARNING

  1. 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.
  2. 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.
  3. If the site does go down, please use your FTP/SSH/cPanel access to restore the .htaccess file from the backup.
  4. 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.

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.

 — PortSwigger

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.

The X-Frame-Options HTTP header remains the most commonly supported clickjacking protection option.

 — Acunetix

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.

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.

 — Kinsta

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! 🙂

Written by
Jinson Varghese
Join the discussion

2 comments