Secure Sitecore : Headers are a headache but nothing we cannot solve!

Lately I have been focussed on OWASP Top 10 security guidelines and locking down sites. The next one on the list is Response Headers. For reach page request, the server sends over the headers containing information about the server and ASP.NET. Some call it chatty headers and less we send back the better it is to protect ourselves.

There are several things you could do to secure your Sitecore instance, namely the Sitecore Security Hardening Guide. Along with the documented steps, there are several others you should implement to secure your instances.

Thank goodness in the newer versions of Sitecore they tackled two of these by default, namely the X-Powered-By:

<httpProtocol> <customHeaders> <remove name="X-Powered-By" /> </customHeaders> </httpProtocol> </system.webServer> 1 2 3 4 5 6 7 8 <httpProtocol> <customHeaders> <remove name = "X-Powered-By" /> </customHeaders> </httpProtocol> </system.webServer>

and X-AspNet-Version (enableVersionHeader as false):

<httpRuntime maxRequestLength="512000" executionTimeout="600" enableKernelOutputCache="false" relaxedUrlToFileSystemMapping="true" enableVersionHeader="false" /> </system.web> 1 2 3 4 <httpRuntime maxRequestLength = "512000" executionTimeout = "600" enableKernelOutputCache = "false" relaxedUrlToFileSystemMapping = "true" enableVersionHeader = "false" /> </system.web>

Next for the X-AspNetMvc-Version HTTP Header, we need to add the following in the Global.asax:

using System; using System.Web.Mvc; namespace TIHIDI.Web { public class Global : Sitecore.Web.Application { protected void Application_Start(object sender, EventArgs e) { MvcHandler.DisableMvcResponseHeader = true; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 using System ; using System . Web . Mvc ; namespace TIHIDI . Web { public class Global : Sitecore . Web . Application { protected void Application _ Start ( object sender , EventArgs e ) { MvcHandler . DisableMvcResponseHeader = true ; }

Last but not the least is the Server header. In order to take this guy out we could add on to the Global.asax, here is the sample code:

protected void Application_PreSendRequestHeaders(object sender, EventArgs e) { HttpApplication app = sender as HttpApplication; if (app != null && app.Context != null) { app.Context.Response.Headers.Remove("Server"); //Response.Headers.Set("Server", "YoMama!"); // you can modify the headers //Response.Headers.Remove("X-AspNet-Version"); //alternate //Response.Headers.Remove("X-AspNetMvc-Version"); //alternate } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 protected void Application _ PreSendRequestHeaders ( object sender , EventArgs e ) { HttpApplication app = sender as HttpApplication ; if ( app != null && app . Context != null ) { app . Context . Response . Headers . Remove ( "Server" ) ; / / Response . Headers . Set ( "Server" , "YoMama!" ) ; / / you can modify the headers / / Response . Headers . Remove ( "X-AspNet-Version" ) ; / / alternate / / Response . Headers . Remove ( "X-AspNetMvc-Version" ) ; / / alternate } }

But where is the fun in that! I usually do not like to fiddle with the Global.asax and so this is an alternate solution to the two fixes above which require Global.asax. This fix relies on defining an Http Module. Lets start by defining a class which inherits IHttpModule:

using System; using System.Web; namespace TIHIDI.SCExtensions.HTTPModules { public class CustomHeadersModule : IHttpModule { public void Init(HttpApplication context) { context.PreSendRequestHeaders += OnPreSendRequestHeaders; } public void Dispose() { } static void OnPreSendRequestHeaders(object sender, EventArgs e) { // remove the Server Http header HttpContext.Current.Response.Headers.Remove("Server"); //remove the X-AspNetMvc-Version Http header HttpContext.Current.Response.Headers.Remove("X-AspNetMvc-Version"); //no need to fiddle with the Global.asax ;) } } } 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 27 using System ; using System . Web ; namespace TIHIDI . SCExtensions . HTTPModules { public class CustomHeadersModule : IHttpModule { public void Init ( HttpApplication context ) { context . PreSendRequestHeaders += OnPreSendRequestHeaders ; } public void Dispose ( ) { } static void OnPreSendRequestHeaders ( object sender , EventArgs e ) { / / remove the Server Http header HttpContext . Current . Response . Headers . Remove ( "Server" ) ; / / remove the X - AspNetMvc - Version Http header HttpContext . Current . Response . Headers . Remove ( "X-AspNetMvc-Version" ) ; / / no need to fiddle with the Global . asax ; ) } } }

Following which lets add it into the Modules section of system.webServer to register the module.

<add name="CustomHeadersModule" type="TIHIDI.SCExtensions.HTTPModules.CustomHeadersModule" /> </modules> 1 2 3 4 <add name = "CustomHeadersModule" type = "TIHIDI.SCExtensions.HTTPModules.CustomHeadersModule" /> </modules>

Both yield the same results, one is cleaner than the other.

If you have any questions or concerns, please get in touch with me. (@akshaysura13 on twitter or on Slack).

Http Module inspiration from IIS 7 – How to send a custom “Server” http header.