We already explained the basics about HTTP Security Headers in this previous post: it's now time to put all these words into action and learn how we can implement them within our NGINX instance to shield our valuable web sites from most dangerous threats.
The first thing we should do is check our website before making any change, to get a grip of how things currently are. Here are some websites that we can use to scan our web site:
- securityheaders.io by Scott Helme (blog, twitter).
- HTTP Security Report by Stefán Orri Stefánsson (twitter).
- Headers Security Test by Geek Flare Tools (website).
Our personal favourite is the first one, as it also has a nice rating system that might help us to understand how protected we are (or not). If your website has no security headers, you'll most likely end up with a severe F rating, just like the following screenshot:
We know, this is our site! We temporarily deactivated everything to be able to get a screenshot that could show the worst possible outcome. If that's your scenario as well, don't worry: you're 1 minute away from ranking up to A !
Without further ado, here's the relevant snippet to place within your Nginx's nginx.conf file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# ----------------------------------------------------- # SECURITY HEADERS - https://securityheaders.io/ # ----------------------------------------------------- # Protects against Clickjacking attacks. # ref.: http://stackoverflow.com/a/22105445/1233379 add_header X-Frame-Options "SAMEORIGIN"; # Protects against Clickjacking attacks. # ref.: https://www.owasp.org/index.php/HTTP_Strict_Transport_Security_Cheat_Sheet add_header Strict-Transport-Security "max-age=63072000; includeSubdomains"; # Protects against XSS injections. # ref.: https://www.veracode.com/blog/2014/03/guidelines-for-setting-security-headers/ add_header X-XSS-Protection "1; mode=block"; # Protects against MIME-type confusion attack. # ref.: https://www.veracode.com/blog/2014/03/guidelines-for-setting-security-headers/ add_header X-Content-Type-Options "nosniff"; # CSP modern XSS directive-based defence, used since 2014. # ref.: http://content-security-policy.com/ add_header Content-Security-Policy "default-src 'self'; font-src *;img-src * data:; script-src *; style-src *;"; # Prevents from leaking referrer data over insecure connections. # ref.: https://scotthelme.co.uk/a-new-security-header-referrer-policy/ add_header Referrer-Policy 'strict-origin'; |
That's about it. These settings are loose enough for most web sites while keeping a strong level of security: you shouldn't have issues with any standard website based upon WordPress, Joomla, Drupal, ASP.NET Core MVC and so on.
In case you need a more relaxed content security policy - for example, if you have media, applets or unsafe scripts & styles - you can tweak that specific line. Here's an example accepting basically everything:
1 |
add_header Content-Security-Policy "default-src 'self'; connect-src *; font-src *; frame-src *; img-src * data:; media-src *; object-src *; script-src * 'unsafe-inline' 'unsafe-eval'; style-src * 'unsafe-inline';"; |
Don't get us wrong, we're not suggesting using it in any way! However, whenever a given scenario would force us to accept anything, having a super-permissive policy it's still better than having none.
And here's our scan after implementing all of the above:
That's it! In case you need to do the same with an Apache web server, read here; to do that with IIS, read here instead.
I sincerely hope that this post will help you to improve the security level of your web site as well.