28

Our site is not currently safe from clickjacking, so I went into the web.config and added

<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name="X-Frame-Options" value="DENY" />
        </customHeaders>
    </httpProtocol>
</system.webServer>

This is very straight forward code. My issue is that it's just not working. The questions I have are:

  1. Is there a way for me to see if the X-Frame-Options is in the header response? I looked for it with httpfox and got nothing, so I can't verify if the web.config is actually putting things in the header.
  2. Why is this not working? What can I do to test or move forward?

I did try to add it in the Global.asax in the Application_Start method, but I cant seem to "hit" this method when I debug; it does not hit breakpoints.

private void Application_Start(object sender, EventArgs e)
{
    // Code that runs on application startup
    HttpContext.Current.Response.AddHeader("x-frame-options", "DENY");

    LogHelper.Info("Cost of Care Web Application Starting");
}

I would like to add that I have tried to add it straight into the head tag and I've also tried to add it in a meta tag like so

<meta http-equiv="X-Frame-Options" content="deny">
Michael
  • 8,362
  • 6
  • 61
  • 88
Moi Hawk
  • 421
  • 1
  • 5
  • 12
  • I've had this issue before and have always found myself having to place the `X-Frame-Options` directly in code: `Response.AddHeader("X-Frame-Options", "DENY");` I couldn't tell you why it doesn't work though as the documentation makes it look like it should. – siva.k Aug 14 '14 at 20:15
  • i searched my solution and found that its already implemented somewhere in the global.asax in the "application_start method .... any more options or advice? – Moi Hawk Aug 14 '14 at 21:12
  • If it's not adding it from Global.asax, what section of Global is it in? – siva.k Aug 14 '14 at 21:15
  • (made an edit above) but its in the "application_start) method – Moi Hawk Aug 14 '14 at 21:54
  • 1
    Create a `protected void Application_BeginRequest(){}` method in Global.asax and add it in there. – siva.k Aug 14 '14 at 23:31
  • YESSSSS!!!!! @IVA.K THANK YOU SO MUCH THAT DID THE TRICK! how do i mark you/that as answer? – Moi Hawk Aug 15 '14 at 22:16
  • Setting it in the config file works fine for me on a web forms app running on both IIS 7.5 and IIS 10.0 – mhenry1384 Sep 29 '16 at 14:30
  • Possible solution: https://stackoverflow.com/questions/11048863/modules-runallmanagedmodulesforallrequests-true-meaning – Edward Olamisan Nov 08 '18 at 19:25

6 Answers6

30

The X-Frame-Options header can be used to control whether a page can be placed in an IFRAME. Because the Framesniffing technique relies on being able to place the victim site in an IFRAME, a web application can protect itself by sending an appropriate X-Frame-Options header.

To configure IIS to add an X-Frame-Options header to all responses for a given site, follow these steps:

  1. Open Internet Information Services (IIS) Manager.
  2. In the Connections pane on the left side, expand the Sites folder and select the site that you want to protect.
  3. Double-click the HTTP Response Headers icon in the feature list in the middle. enter image description here
  4. In the Actions pane on the right side, click Add.
  5. In the dialog box that appears, type X-Frame-Options in the Name field and type SAMEORIGIN or DENY in the Value field. enter image description here
  6. Click OK to save your changes.
Vladislav
  • 1,696
  • 27
  • 37
Voltur
  • 401
  • 4
  • 2
25

Since my comments answered the question here's the end result:

For some reason setting the X-Frame-Options in web.config doesn't seem to actually work even though the documentation makes it sound like it should.

An easy work around is to set the headers manually using:

Response.AddHeader("X-Frame-Options", "DENY");

If you need this set for every request with no exceptions you can add the Application_BeginRequest to Global.asax:

protected void Application_BeginRequest()
{
    Response.AddHeader("X-Frame-Options", "DENY");
}
siva.k
  • 1,344
  • 14
  • 24
14

The answer of siva.k does not work in connection with MVC5 as the header is generated twice here. The following code should work:

protected void Application_Start()
{
  //  MVC5 generates the "X-Frame-Options SAMEORIGIN" header by default, the following line disables the default behaviour
  System.Web.Helpers.AntiForgeryConfig.SuppressXFrameOptionsHeader = true;
}

protected void Application_BeginRequest() 
{
  Response.AddHeader("X-Frame-Options", "DENY");
}

The SuppressXFrameOptionsHeader flag was mentioned here: https://stackoverflow.com/a/20262211/3936440

Community
  • 1
  • 1
ViRuSTriNiTy
  • 5,017
  • 2
  • 32
  • 58
9
<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name="Content-Security-Policy" value="default-src: https:; frame-ancestors 'self' X-Frame-Options: SAMEORIGIN" />
        </customHeaders>
    </httpProtocol>
</system.webServer>

Your web.config entry needs to be under content security policy to make use of current coding not previously depreciated. The value under content security policy of value="default-src: https: is unique to your website.

The content that matters is what comes after 'value="default-src: https:' but most importantly is contained within Content Security Policy.

Brian Kunick
  • 139
  • 1
  • 3
  • 2
    This is the right way to go, but the directive "frame-anscestors 'self';" should stop there, with a semicolon, not then continue to X-Frame-Options, which is meaningless in this header. – Corrodias Sep 18 '20 at 21:28
5

Here is another thing to consider:

If you have a separate back-end and UI projects (as is very common for REST based sites), make sure that you put X-Frame-Options in the UI web.config. Your API is probably allowing cross site calls so adding the header to your API project would make no sense.

MarzSocks
  • 4,229
  • 3
  • 22
  • 35
2

I found that some file types (.asp and .htm files) were getting the X-Frame-Options header added by this mechanism and others (.js) weren't. Using the IIS Admin utility I removed the header from the application level and added it at the server level, and then all files were getting the header added.

BlueMonkMN
  • 25,079
  • 9
  • 80
  • 146