
Adding HSTS To Your Website
So you’ve moved your website to use SSL/TLS and that’s it? Not quite! Your next step should to test your site and enable HSTS (HTTP Strict Transport Security).
Changelog
19Dec2017 – Originally posted
5Apr2018 – Added speed difference verbiage between server config and functions.php or .htaccess for high volume websites
Testing via Qualys SSL Labs
I *love* the SSL Labs server test from Qualys. It’s free and it does a fantastic job of testing (and subsequently grading) your website for cipher suites, protocols (SSL/TLS versions), etc. IMO, it should be one of the first checks performed after standing up a website and then periodically checked every X number of months after that. The beauty of the tests is that pretty much everyone understands the grading system so if your site receives a B, you are going to wonder how you could make that an A… Unless you are just a classic underachiever! 😉
Simply go to the website below, type in your hostname (example: www.linuxincluded.com), click submit, and wait a bit.
https://www.ssllabs.com/ssltest/index.html
There are a ton of possible issues why you might not get a ‘B’ score or worse such as cipher suites, protocols, etc. I won’t go into each of those because 1) there really are a million reasons why and 2) they are easily understood/explained. One common issue that isn’t quite so obvious is why your website is stuck at an ‘A’ and an ‘A+’ score remains elusive. Fortunately, it is most likely a rather simple solution involving HSTS.
What is HSTS?
HSTS protects your website against against protocol downgrade attacks. A protocol downgrade attack would allow a man-in-the-middle to send an unknowing user to an http version of your site instead of an https version. To combat this, when someone goes to your site, it receives a “Strict-Transport-Security” response header which it then caches based on the “max-age” setting. Thus, on subsequent visits it knows the site should be https even if someone is trying to perform the downgrade attack. Because it requires MiTM, it’s not a common attack vector most would worry about, but if you enabled https on your site you might as well make sure your users are using it. Going back to the results from SSL Labs, if you scroll down and look under “Protocol Details” you will see a couple of references to HSTS. Assuming HSTS is not enabled, you will see ‘No’ as in the example below.
There are several ways to add HSTS to your site. Make sure you only add it one way or you may receive unexpected results.
Option 1: Adding HSTS via WordPress plug-in
WordPress also has a plug-in available for this and it works ok if you are adverse to modifying files by hand. Simply go to Add Plugins, search for HSTS, and install the one below. After clicking ‘install’ and ‘activate’ you are done!
One issue with this approach is that your website will only have HSTS on the URL in the WordPress Address (Settings -> General), but not the forwarded site. For example, www.linuxincluded.com would show HSTS is enabled, but linuxincluded.com would not. If you flip-flop and change the WordPress Address to linuxincluded.com, then www.linuxincluded.com wouldn’t be HSTS.
Maybe that isn’t a big deal? If not, leave well enough alone. Another minor caveat is that by default, the plug-in also has the max-age as 15984000. This means you can’t apply for inclusion into the pre-load list (discussed below in the “Going further” section).
Option 2: Adding HSTS via WordPress functions.php file <- my preferred way
Another way to add HSTS in WordPress is via the functions.php file for your theme. If you use cPanel, go to file manager and then select web root as shown below.
From there, go to wp-content, themes, double-click your theme name, select functions.php and then click edit.
If you don’t have cPanel, no problem. You can navigate to the functions.php file in a similar fashion, although your initial folder might be slightly different depending on your install.
if (is_ssl()) { header('Strict-Transport-Security:max-age=31536000; includeSubdomains; preload'); }
Also note the if statement checks whether the page is SSL. The “if” is not 100% necessary, but the HSTS pre-load website complains if you don’t have it via the warning below “unnecessary HSTS header over HTTP.”
Keep in mind that since the change was made to the theme, if your website theme ever changes, you will need to re-add the code above to the functions.php file. Alternatively, you could add any of the code below to your web server instead of modifying the functions.php file.
If you have a high-volume website, I would suggest using the respective server configurations below instead of the functions.php or .htaccess methods. Unfortunately, the server configuration file isn’t accessible in many hosted environments.
Option 3: Adding HSTS on Apache
You can add the following to your .htaccess file in the public_html directory. If you have access to the Apache configuration file, you should make this change in the VirtualHost section instead of using .htaccess. The reason for this is because .htaccess is often regarded as slow and in most cases, it should be avoided. Don’t forget that if the server configuration is modified, a restart of Apache is needed.
Header set Strict-Transport-Security "max-age=31536000" env=HTTPS
Option 4: Adding HSTS on nginx
Simply add this to the server block of your HTTPS config. Restart nginx.
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
Option 5: Adding HSTS on IIS
Open the Internet Information Services (IIS) Manager (Start → Administrative Tools → IIS Manager). Click on HTTP Response Headers, then click on Add (in the Actions panel). Add the following values in the Add Custom HTTP Response Headers dialog box and restart IIS.
Name: Strict-Transport-Security Value: max-age=31536000
Testing
You can go back to SSL Labs and test to ensure HSTS is properly enabled. If the SSL Labs site query comes back quickly and HSTS still says no, make sure you click ‘Clear cache’ so it re-runs the test.
Alternatively, you can test from the command line.
# curl -s -D- https://linuxincluded.com |grep -i "strict-" Strict-Transport-Security: max-age=31536000; includeSubDomains; preload # curl -s -D- https://linuxincluded.com |grep -i "strict-" Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Neither of the http queries should return the header.
# curl -s -D- http://linuxincluded.com |grep -i "strict-" # curl -s -D- http://linuxincluded.com |grep -i "strict-"
Going further
If you are really worried about security and https/HSTS, then I would strongly suggest you look at HSTS preloading. Preloading adds your site to a pre-installed “local” list where it is *not* dependent on the first visit as described above. Most of the major browsers such as Chrome, Firefox, and Edge support it. The website below does a fantastic job of preparing you for this change and understanding exactly what it encompasses.
Adding submitting, you will receive a “success” message back stating your website is pending approval in the HSTS preload list.

Dallas Haselhorst has worked as an IT and information security consultant for over 20 years. During that time, he has owned his own businesses and worked with companies in numerous industries. Dallas holds several industry certifications and when not working or tinkering in tech, he may be found attempting to mold his daughters into card carrying nerds and organizing BSidesKC.
4 thoughts on “Adding HSTS To Your Website”
Great article!
I especially like the functions.php solution, which I saw nowhere else. Do you believe it would be equally fast with the .htaccess solution?
And how about the .htaccess for Nginx
Thanks
Thanks! The functions.php script is something I wrote as I worked through adding HSTS to WordPress sites. The error message about the unnecessary HSTS header over HTTP bugged me when I submitted sites for HSTS pre-loading. If you are working with high volume sites, I would definitely recommend adding the headers in the respective server configurations instead of in .htaccess or the functions.php as you will likely see a slight speed increase. I’ll add this recommendation to the write-up. Also, based on documentation from the nginx.com website regarding .htaccess, “You can’t do this. You shouldn’t. If you need .htaccess, you’re probably doing it wrong.” 😉
Your article are great. Thank you !
Thanks for the feedback!