13

I have added the following X-frame-options header in web.config:

<httpProtocol>
  <customHeaders>
    <remove name="X-Powered-By" />

    <add name="X-Frame-Options" value="sameorigin" />   

  </customHeaders>
</httpProtocol> 

Despite adding this header, our security scan still recommends that anti-framing measures need to be taken. How do we implement X-Frame-options properly?

I want to set the HTTP response header with X-frame-options that should reflect across application, with sameorigin.

Please suggest that is this approach is correct or if it needs to be implemented differently in Sitecore?

3
  • 2
    Possible duplicate of How to set X-Frame-Options to deny? Aug 24 '18 at 16:56
  • 1
    I want to set x-frame options in HTTP header .the above URL is to deny.i am trying to figure where I have to write HTTP response header to apply all over the solution
    – sindu
    Aug 24 '18 at 17:15
  • I agree the above is a different question and there have been changes in the Sitecore 8.2 update-4 code that means this is not 100% correct any more.
    – jammykam
    Aug 25 '18 at 13:43
14

Yes, this is one of the recommended approaches to prevent clickjacking, and adding the X-frame-options header is one of the required steps.

After making the changes to the web.config, you should see that X-frame-options should be present in the response headers.

You should also ensure that relevant Content Security Policy headers have also been set.

Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement to distribution of malware.

Source: Mozilla Developer Network

I suspect this is the reason your security scan is still failing. Setting the frame-ancestors is one of the OWASP recommendations to prevent clickjacking.

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <remove name="X-Powered-By" />
      <add name="X-Frame-Options" value="SAMEORIGIN" />
      <add name="Content-Security-Policy" value="frame-ancestors 'self'" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

With these config changes in place, you should now see the following response headers being returned:

Content Security Policy headers

I recommend you check the security headers present on your website using https://securityheaders.com/ which will scan the security headers present and you can see what else you might be missing. Note that this tool can only work against a live, publicly accessible site, i.e. you can check your local website.

I also recommend reading these blog posts by Akshay Sura and Bas Litjen which contain a number of other recommendations.

Sitecore X-Frame-Options module

Sitecore has introduced an X-frame-options module, which is included by default in the web.config as an http module:

<system.webServer>
  <modules runAllManagedModulesForAllRequests="true">
    <add type="Sitecore.Web.XFrameOptionsHeaderModule, Sitecore.Kernel" name="SitecoreXFrameOptionsHeaderModule" />
  </modules>
</system.webServer>

Prior to Sitecore 8.2 Update-4, this would add an X-frame-options='sameorigin' header to be added to all requests. However a change was made in this version to so this header was only added to backend requests to the CMS (by checking that the security domain of the requested site is 'sitecore')

122317: The XFrameOptionsHeaderModule module picks up front-end requests.

For earlier versions, using Outbound Rules of the URL Rewrite in IIS is the recommended way to change the header. For Sitecore 8.2 onwards you need to handle this yourself and add the headers you require, including X-frame-options.

This leads to a problem that the X-frame-options will be inserted twice for requests to the backend admin. Options to mitigate this are:

  • Only add the customHeaders on your CD servers
  • Create a custom Http Module and add it to web.config modules section in a similar way that to the Sitecore XFrameOptionsHeaderModule, and add a check to only add the header if it is not already present.
  • Use a slightly more advanced outbound rule to only insert the header when it is not present using preconditions:
<httpProtocol>
  <customHeaders>
    <remove name="X-Powered-By" />
    <add name="Content-Security-Policy" value="frame-ancestors 'self'" />
  </customHeaders>
</httpProtocol>
<rewrite>
  <outboundRules>
    <rule name="Add RESPONSE_X-Frame-Options" preCondition="X-Frame-Option not present">
      <match serverVariable="RESPONSE_X_Frame_Options" pattern=".*" />
      <action type="Rewrite" value="SAMEORIGIN" />
    </rule>
    <preConditions>
      <preCondition name="X-Frame-Option not present">
        <add input="{RESPONSE_X_Frame_Options}" pattern=".+" negate="true" />
      </preCondition>
    </preConditions>
  </outboundRules>  
</rewrite>

This will insert the X-Frame-Options header only if is has not already been set, so will allow the Sitecore XFrameOptionsHeaderModule to insert the header for the backend and independently allow you to insert the header for your frontend/CD sites.

1
  • For Sitecore 9.3 onwards, if you will add <add name="Content-Security-Policy" value="frame-ancestors 'self'" /> then Horizon site will not load Sitecore site for Editing Experience, so no need to use <add name="Content-Security-Policy" value="frame-ancestors 'self'" /> from above mentioned configurations.
    – Amit Kumar
    Oct 7 '20 at 10:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.