HTTP Strict Transport Security (HSTS) is a standard to protect visitors by ensuring that their web browsers are always connected via HTTPS. It is a security mechanism that helps to protect websites from man-in-the-middle attacks (MITM).
- How does man-in-the-middle attack work?
- What does an HSTS-enabled website do?
- How do I enable HSTS on a web server?
- Set the Strict Transport Security header on Nginx
- Set the Strict Transport Security header on Apache
- Set the Strict Transport Security header in Flask applications
- Set the Strict Transport Security header in NodeJS applications
- How to test if a website is HSTS-enabled
- Did this work for you?
How does man-in-the-middle attack work?
If the browser connects to a website, say a banking website, a hacker can intercept the communication between both parties - the user and the bank website. The hacker can modify the web traffic. A possible scenario is when using a public wifi at a coffee shop or the airport. The hotspot may be a malicious one run by a hacker, who can later monitor the activity and change important information in transit.
In the worst case, the hacker can make money transfers using the banking website after intercepting the web traffic. Now, all this happens when the web traffic is sent via http://
instead of via https://
.
A common approach for a web server is to accept both http and https connections. If the user requests a website through http, they get redirected to the https version. This can lead to an MITM attack.
What does an HSTS-enabled website do?
When a user visits an HSTS-enabled website, the browser always uses an https://
connection even when clicked on an http://
URL. It does this by instructing browsers to only connect to the website using HTTPS, and to never backtrack to HTTP.
When the browser encounters the Strict-Transport-Security
in the response header, it knows that it can only access the website via https and not http, even if requested by http.
The browser also updates the expiration time for the website from the time (in seconds) sent by the web server.
You can read the standards document from ietf.org.
How do I enable HSTS on a web server?
To enable HSTS, at the very least, the web server returns something like this in the response headers:
Strict-Transport-Security: max-age=31536000;
The above response tells the browser to enable HSTS for that domain or subdomain for 31536000
seconds, which translates to one year.
If you want to make the browser remember for 2 years, the web server is configured to return this in the headers (63072000 seconds is 2 years):
Strict-Transport-Security: max-age=63072000;
If we want to extend the HSTS policy to all the subdomains in that website, so we add includeSubDomains
:
Strict-Transport-Security: max-age=31536000; includeSubDomains;
A third addition is to use the preload
parameter so that the browser caches the HSTS policy in its cache.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
The recommended response is to send something like this:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Set the Strict Transport Security header on Nginx
Add this block of code to nginx.conf or conf file for that domain:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
Restart your Nginx web server.
sudo systemctl restart nginx
Set the Strict Transport Security header on Apache
Add this block of code to your .htaccess
or htaccess conf file:
<IfModule mod_headers.c>
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" env=HTTPS
</IfModule>
Restart your Apache web server.
sudo systemctl restart apache2
Set the Strict Transport Security header in Flask applications
If you have a Python Flask application running and it returns the headers directly use this code. You can add it in an after_request
decorator:
@app.after_request
def add_hsts(response):
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains; preload'
return response
This is a fully working Flask program that has enabled HSTS:
app.py
from flask import Flask
app = Flask(__name__)
@app.after_request
def after_request_func(response):
response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains; preload'
return response
@app.route("/")
def index():
print('Hello!')
if __name__ == "__main__":
app.run()
Set the Strict Transport Security header in NodeJS applications
If you have a NodeJS application running on ExpressJS and it returns the headers directly, you can use Helmet library. This code should work:
app.use(
helmet.hsts({
maxAge: 31536000,
includeSubDomains: true,
preload: true,
})
);
How to test if a website is HSTS-enabled
To test if a website (say aruljohn.com) has enabled HSTS, run this on the command line:
curl -sI https://aruljohn.com | grep -i 'strict-transport'
The output will be like this:
$ curl -sI https://aruljohn.com | grep -i 'strict-transport'
strict-transport-security: max-age=31536000; includeSubDomains; preload
If HSTS is not enabled, the grepped response will be blank.
Did this work for you?
If this did not work for you or you have any questions, always feel free to contact me and I will try to reply within 24-48 hours.
Related Posts
If you have any questions, please contact me at arulbOsutkNiqlzziyties@gNqmaizl.bkcom. You can also post questions in our Facebook group. Thank you.