Securing Response Headers Based on Sitecore Helix Conventions
Overview
HTTP security headers provide another layer of security by helping to mitigate attacks and security vulnerabilities. Missing security headers help the attacker to launch advanced attacks by clubbing multiple individual ones.
It is important to add the security headers, in my application I added the following headers:
- X-XSS-Protection
- Strict-Transport-Security
- X-Content-Type-Options
- Content-Security-Policy
Let's talk a little bit about each one of these headers that we want to add and what they can do.
X-XSS-Protection This header can be used to enable the user agent's built-in reflective XSS protection. Internet Explorer, Chrome, and Safari support this header. I will set the value for this header to "X-XSS-Protection: 1; mode=block" to enable the user's agent protection.
Strict-Transport-Security This header is for configuring user agents (browsers) to only communicate to the server over a secure transport. It is primarily used to protect against man-in-the-middle attacks by forcing all further communications to occur over TLS.
I will set the value for this header to "max-age=31536000; includeSubDomains; preload" In my case the website is only accessible by HTTPS.
X-Content-Type-Options
This header is used to protect against MIME-type attacks in Internet Explorer, Chrome, and also Safari.
I will set the value for this header to "nosniff".
Content-Security-Policy
This header enables you to reduce the risk of XSS attacks by allowing you to define where resources can be loaded from, preventing browsers from loading data from any other locations. This makes it harder for an attacker to inject malicious code to your site.
Refer to this link for more information:
http://stackoverflow.com/questions/30280370/how-does-content-security-policy-work
Let's assume that I want to set this header to default-src 'self'
Adding security headers In Sitecore
There are many ways to add these headers to your applications, this can be done from the web.config, or it can be done from Global.asax using Application_PreSendRequestHeaders event. In this blog, I want to point out how we can add these headers using Helix conventions.
Using Helix Conventions
We have to consider that we are working on Sitecore multi-site instance, these headers will be added to all of the sites on the same Sitecore instance.
Since we are following Helix conventions, this implementation should live in the lowest level (foundation layer) as this implementation will impact many other modules.
Typically, modules in the Foundation layer are either business-logic specific extensions on the technology frameworks used in the implementation, or shared functionality between feature modules that is abstracted out into separate frameworks. http://helix.sitecore.net/principles/architecture-principles/layers.html
The steps to do this is:
- Create a new web project on the foundation layer and name it [PROJECTNAME].Foundation.Security.
- We need to create a custom Pipeline that inherits HttpRequestProcessor and add the security headers to the HTTP response. The logic for the pipeline is to add the security headers to the response.
- The last thing we need to add a folder called "Foundation" in the app_config of the project and add a new config file called "Foundation.Security.config" . In this config file, we need to add the processor that we have created to the httpRequestEnd or httpRequestProcessed Pipelines.
public class ResponseHeadersSecurityHardening : HttpRequestProcessor { private const string _xframeOptionsHeaderKey = "X-Frame-Options"; private const string _xcontentTypeOptionsHeaderKey = "X-Content-Type-Options"; private const string _xxssProtectionHeaderKey = "X-XSS-Protection"; private const string _contentSecurityPolicy = "Content-Security-Policy"; private const string _strictTransportSecurity = "Strict-Transport-Security"; public override void Process(HttpRequestArgs args) { try { this.Execute(args.Context.Response); } catch (Exception exception) { Log.Error("[PROJECTNAME].Foundation.Security An error occured processing the response headers.", exception, this); } } public void Execute(HttpResponse response) { if (!response.Headers.AllKeys.Any<string>((string h) => h == _xcontentTypeOptionsHeaderKey)) { response.Headers.Add(_xcontentTypeOptionsHeaderKey, "nosniff"); } if (!response.Headers.AllKeys.Any<string>((string h) => h == _xxssProtectionHeaderKey)) { response.Headers.Add(_xxssProtectionHeaderKey, "1; mode=block"); } if (!response.Headers.AllKeys.Any<string>((string h) => h == _contentSecurityPolicy)) { response.Headers.Add(_contentSecurityPolicy, "default-src 'self'"); } if (!response.Headers.AllKeys.Any<string>((string h) => h == _strictTransportSecurity)) { response.Headers.Add(_strictTransportSecurity, "max-age=31536000; includeSubDomains; preload"); } } }
For more information about the security headers, please refer to this link:
https://www.veracode.com/blog/2014/03/guidelines-for-setting-security-headers
PS: Don't just copy and paste this code, these headers can be set to different values according to your case, even It might break your front end. After using the headers you have to test your site and Sitecore CMS.