What are security headers, and how can I use them to help better secure my website?
When creating your awesome new website (I am sure it is super awesome!), there are a few commonly missed security aspects you should consider to help keep your website safe. I'll list some common ones that I feel are relevant.
What are security headers
The term "security headers" is a really just a blanket term used to describe headers that are sent to the browser from the server that can help prevent some common issues with XSS and other types of attacks. These headers provide instructions to the browser about the policies you create for your website, such as not allowing images to load from other websites, all the way to disallowing microphone access.
When should I think about using them?
I personally find it a good practice to consider using these types of headers early on in the development of a new project for 4 reasons.
• Your project planning, involving resources, can be better thought out
• It forces you to use good practices right from the start
• You know your future visitors can be safe from these types of attacks up front
• Implementing things like CSP later on could be rather difficult
When you consider the above 4 reasons, it can be very convenient to think about and implement these types of protections early on in a projects lifespan.
Who should use them?
This is a very good question that is certainly specific to each individual application. For example, maybe your project is an internal one that only you and a handful of trustworthy people use and therefore it is not really a high priority. Other times however, you may work on a project that is open to the public or otherwise can be consumed by large numbers of individuals, and you may consider this a higher priority.
Additionally for large existing applications, some of the recommendations may be too restrictive, as it may require changing the entire flow or aspect of large features or an entire application itself. So it is important to evaluate your own applications needs and how it may fit into some of these types of policies.
Below, I will list some headers that may be of interest and offer some details on each one.
# Deny all frames
# Deny frames not from your hostname
This header is useful for not allowing your website to be loaded inside of iframes, frames, objects or embeds. For example, let's say an attacker wraps your website in an iframe, and above the iframe they add a login feature of their own. This could effectively trick a user of your website into entering their credentials into a website not owned by you.Pro: Prevent your website from being put into an attackers frame on their website Con: Disallowing your website from being put into a frame for legitimate reasons (eg: youtube embedded videos)
This header can also be considered deprecated when using CSP (Content Security Policies) which we'll go into below.
This can be a useful addition to any website. This tells the browser to use the mime type specified by the server, such as "text/css" by a stylesheet and not to try and guess the content type if it believes it is something different than what the server specified. This keeps you in control of the content and can help prevent an issue where your content can be misinterpreted by the browser and be rendered in unexpected ways, which could lead to security issues.
This also enables CORB (Cross-Origin Read Blocking) on some resources as well, which prevents the browser from delivering certain cross-origin network responses to a web page, when they might contain sensitive information and are not needed.Pro: Ensure the right content is being delivered and protectedCon: None
# Recommended: No referrer information sent
# Do not send referrer info when going from https to http
# Only send the origin
# Send the origin, path, and query string when it is the same origin and same protocol level. Send only the origin for cross origin requests and requests to less secure destinations
# Send the origin, path, and query string for same-origin requests
# Second Best: Send only the origin when the protocol security level stays the same and do not send to less secure destinations
# Default: Send the origin, path, and query string when performing a same origin request. For cross-origin requests only send the origin when the protocol security level stays same. Do not send to less secure destinations
# Not Recommended: Send it all to everywhere
This has a lot of options, but in security terms; This can prevent sending information to websites that might not be in your control or accidentally leaking potential sensitive information. A good article to read on why this is important, would be this one (which we are not going to be sending your referring information to as well 😊):The referrer problemPro: Protecting your visitors information a little betterCon: Understanding your applications needs to share information between different applications
Content-Security-Policy: default-src 'none';
There is certainly an extensive list of directives this policy takes so I won't cover them all, but I will explain the essential concept and provide links to documentation and a neat little site you can use to generate a policy.
default-src 'none'; script-src 'self'; style-src 'self' fonts.googleapis.com; img-src 'self'; font-src 'self' fonts.gstatic.com; frame-ancestors 'none'; form-action 'self'; upgrade-insecure-requests; disown-opener; base-uri 'self'
Whoa, that is a long string. Lets break it down one by one:
• default-src 'none'; This tells the browser that the default src for all of my resources is nothing. This means for example if I do not specify a src for images, no images will load.
• script-src 'self'; Only this website ('self') can load scripts, scripts from 3rd parties will not load
• style-src 'self' fonts.googleapis.com; Only this website, and "fonts.googleapis.com" can load stylesheets
• img-src 'self'; Only this website can load images
• font-src 'self' fonts.gstatic.com; Only this website, and "fonts.gstatic.com" can load fonts
• frame-ancestors 'none'; This website will not load in frames, similar to the "X-Frame-Options" header discussed above
• form-action 'self'; This website can only submit forms to itself
• upgrade-insecure-requests; This one is pretty optional, and not necessarily needed by this website specifically. Its intent is to opportunistically load http resources as http
• base-uri 'self'; Only this website can be used in a element
More reading:Content-Security-PolicyAuto-generate CSP
There are a few good websites you can use to test some of these headers and more. I'll list a few links below:Mozilla ObservatorySecurity HeadersGeek Flare
I created a small WordPress plugin to test your WordPress website for these types of headers. I'll link a zip file and a link to the GitHub repo below.Download PluginView Source Code
Wrapping things up
There are definitely more headers to consider, such as "Strict-Transport-Security" which requires your website only load in https, and some cross origin request headers. This is just a basic list of things you can do to get started and hopefully set you up on a path to a more secure application. Like previously stated, these things will not directly apply to every situation, so it is best to analyze individual applications to determine your own best path forward.