RFC 7034

HTTP Header Field X-Frame-Options

πŸ“… published October 2013, from ietf

RFC 7034: HTTP Header Field X-Frame-Options πŸŽ€

Okay bestie, this is RFC 7034 and it is giving clickjacking defense πŸ’… The title is HTTP Header Field X-Frame-Options, and it's an Internet Engineering Task Force (IETF) doc.

It was written by D. Ross of Microsoft and T. Gondrom of Thames Stanley 🧚 It's in the Informational category, so it's not a Standards Track spec. It's more of a "here's how this works" explainer πŸ’œ The ISSN is 2070-1721 and the date is October 2013 πŸ“ The title block doesn't list any RFCs that it obsoletes or updates.

Abstract ✨

Okay so the big goal here is making web apps safer from clickjacking πŸ›‘οΈ This doc describes the X-Frame-Options HTTP header field. It's a policy the server sends to the browser, and it says whether the browser is allowed to show that content inside frames that live on other web pages πŸ–ΌοΈ

Status of This Memo πŸ“‹

This document is not an Internet Standards Track specification. It's published for informational purposes, so no cap, it's not a rulebook πŸ™ˆ

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG). Not every doc the IESG approves is a candidate for any level of Internet Standard. See Section 2 of RFC 5741 for that.

Info about the current status of this document, any errata, and how to send feedback is at http://www.rfc-editor.org/info/rfc7034 πŸ”—

Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as they stand on the date this document was published. Please review these documents carefully, because they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions. They're provided without warranty, as described in the Simplified BSD License.

Table of Contents πŸ“š

1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  3
  1.1.  Requirements Language  . . . . . . . . . . . . . . . . . .  3
2.  X-Frame-Options Header . . . . . . . . . . . . . . . . . . . .  4
  2.1.  Syntax . . . . . . . . . . . . . . . . . . . . . . . . . .  4
  2.2.  Augmented Backus-Naur Form (ABNF)  . . . . . . . . . . . .  5
    2.2.1.  Examples of X-Frame-Options  . . . . . . . . . . . . .  6
  2.3.  Design Issues  . . . . . . . . . . . . . . . . . . . . . .  6
    2.3.1.  Enable HTML Content from Other Domains . . . . . . . .  6
    2.3.2.  Browser Behavior and Processing  . . . . . . . . . . .  6
      2.3.2.1.  Violation of X-Frame-Options . . . . . . . . . . .  6
      2.3.2.2.  Variation in Current Browser Behavior  . . . . . .  7
      2.3.2.3.  Usage Design Pattern and Example Scenario for
                the ALLOW-FROM Parameter . . . . . . . . . . . . .  8
      2.3.2.4.  No Caching of the X-Frame-Options Header . . . . .  8
3.  IANA Considerations  . . . . . . . . . . . . . . . . . . . . .  9
  3.1.  Registration Template  . . . . . . . . . . . . . . . . . .  9
4.  Security Considerations  . . . . . . . . . . . . . . . . . . .  9
  4.1.  Privacy Considerations . . . . . . . . . . . . . . . . . . 10
5.  References . . . . . . . . . . . . . . . . . . . . . . . . . . 10
  5.1.  Normative References . . . . . . . . . . . . . . . . . . . 10
  5.2.  Informative References . . . . . . . . . . . . . . . . . . 11
Appendix A.  Browsers That Support X-Frame-Options . . . . . . . . 13
Appendix B.  Description of a Clickjacking Attack  . . . . . . . . 13
  B.1.  Shop . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
  B.2.  Online Shop Confirm Purchase Page  . . . . . . . . . . . . 13
  B.3.  Flash Configuration  . . . . . . . . . . . . . . . . . . . 13
Appendix C.  Acknowledgements  . . . . . . . . . . . . . . . . . . 13

1. Introduction 🌸

Back in 2009 and 2010, a bunch of browser vendors ([Microsoft-X-Frame-Options], [CLICK-DEFENSE-BLOG], and [Mozilla-X-Frame-Options]) started using a non-standard HTTP [RFC2616] header field called "X-Frame-Options" to guard against clickjacking [Clickjacking]. HTML-based web apps can embed or "frame" other web pages πŸͺŸ Clickjacking is when an attacker stacks multiple transparent or opaque layers in the UI to trick a user into clicking a button or link on another page, from server B, when they thought they were clicking the same spot on the overlaying page from server A. So the attacker is "hijacking" clicks meant for page A and routing them to page B 😭 The attacker is tricking the user, who sees the overlaying UI from page A, into clicking specific spots on the page underneath from server B. That can trigger actions on server B and maybe use an existing session context in that step. It's an attack on both the user and on server B. Also, server A may or may not be the attacker πŸ’€

This spec gives informational docs about how X-Frame-Options is currently used and defined. As Section 2.3.2.2 explains, not every browser implements X-Frame-Options in exactly the same way, and that can lead to unintended results ⚠️ Plus, since the "X-" construction is deprecated [RFC6648], the X-Frame-Options header field will eventually be replaced by the Frame-Options directive in the Content Security Policy (CSP) version 1.1 [CSP-1-1] πŸ¦‹

A study [FRAME-BUSTING] showed that existing anti-clickjacking measures, like frame-breaking JavaScript, have weaknesses that let attackers get around them 😀

Unless you configure the browser to disable frames and scripts entirely (which massively wrecks browser utility), browser users are vulnerable to this kind of attack πŸ₯²

X-Frame-Options lets a web page from host B declare that its content (like a button, links, text, etc.) must not be displayed in a frame (<frame> or <iframe>) of another page, like one from host A. That's done with a policy declared in the HTTP header and enforced by browser implementations, as documented here πŸ‘‘

1.1. Requirements Language 🧾

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119 [RFC2119]. Yes, these are the official BCP 14 key words, so read them carefully πŸ€“

2. X-Frame-Options Header πŸ’–

The X-Frame-Options HTTP header field indicates a policy that says whether the browser should render the transmitted resource within a <frame> or an <iframe>. Servers can put this policy in the header of their HTTP responses to prevent clickjacking attacks, which makes sure their content doesn't get embedded into other pages or frames 🫢

2.1. Syntax πŸŽ€

The header field name is:

X-Frame-Options

There are three different values for the header field. They're mutually exclusive, which means the header field MUST be set to exactly one of the three values πŸ’…

DENY A browser receiving content with this header field MUST NOT display this content in any frame.

SAMEORIGIN A browser receiving content with this header field MUST NOT display this content in any frame from a page of a different origin than the content itself.

If a browser or plugin cannot reliably determine whether or not the origin of the content and the frame are the same, this MUST be treated as "DENY". Not me being like "when in doubt, block it" πŸ™…β€β™€οΈ

Please note that current implementations vary on how they interpret this criterion. In some, a page can only be framed if the origin of the top-level browsing context is identical to the origin of the content using the X-Frame-Options directive. In others, the browser may look at the origin of the framing page instead. Check Section 2.3.2.2 for more on frame nesting and how different browsers handle this header field. Also, see Section 4, paragraph 2 for the security problems that can result πŸ”

ALLOW-FROM (followed by a serialized-origin [RFC6454]) A browser receiving content with this header MUST NOT display this content in a frame from any page whose top-level browsing context has a different origin than the specified origin. This can expose the page to risks from the trusted origin, but in some cases it may be necessary to allow framing by content from other domains πŸ₯Ί

The meaning of the term "serialized-origin" is given in [RFC6454]. If the ALLOW-FROM value is used, it MUST be followed by a valid origin [RFC6454] (as a subset of the URI [RFC3986]) 🧐

Any data beyond the domain address (i.e., any data after the "/" separator) is to be ignored. The algorithm to compare origins from [RFC6454] SHOULD be used to check that a referring page has the same origin as the content (for SAMEORIGIN), or that the referring page's origin is identical to the ALLOW-FROM serialized-origin (for ALLOW-FROM). Here's the tea β˜• Even though it conflicts with [RFC6454], current implementations don't treat the port as a defining part of the origin. So existing implementations differ from [RFC6454] in that origins with the same protocol but different port values are considered equivalent πŸ‘€

Wildcards, or lists that declare multiple domains in one ALLOW-FROM statement, are not permitted (see Section 2.3.2.3). Sorry, no wildcard glow-up here 🚫

2.2. Augmented Backus-Naur Form (ABNF) 🧩

The RFC 5234 [RFC5234] ABNF of the X-Frame-Options header field value is the following:

         X-Frame-Options = "DENY"
                   / "SAMEORIGIN"
                   / ( "ALLOW-FROM" RWS SERIALIZED-ORIGIN )

         RWS             = 1*( SP / HTAB )
                       ; required whitespace

It uses serialized-origin as defined in [RFC6454] and required whitespace (RWS) as defined in [HTTPbis-P1] 🌈

RWS is used when at least one linear whitespace octet is required to separate field tokens. RWS SHOULD be generated as a single space (SP). Multiple RWS octets that occur within field-content SHOULD either be replaced with a SP or transformed into all SP octets before the field value is interpreted or the message is forwarded downstream 🧹

SP and horizontal tab (HTAB) are defined in Appendix B.1 of RFC 5234 [RFC5234] ✨

The values are specified as ABNF strings, so they're case-insensitive. Yep, that means deny and DENY are the same vibe 🀭

2.2.1. Examples of X-Frame-Options 🍭

X-Frame-Options: DENY

X-Frame-Options: SAMEORIGIN

X-Frame-Options: ALLOW-FROM https://example.com/

2.3. Design Issues πŸ› οΈ

2.3.1. Enable HTML Content from Other Domains 🌍

There are a few main direct ways that HTML content from other domains can get enabled, and browser implementations of X-Frame-Options cover all of them:

  • IFRAME tag
  • Frame tag
  • Object tag (requires a redirect)
  • Applet tag
  • Embed tag

Besides these, there might be other ways to host HTML content. For example, some plugins may host HTML views directly. If those plugins show up essentially as frames (as opposed to top-level windows), the plugins must conform to the X-Frame-Options policy specified in this document too 🧚 Ooh, this part is so important, don't skip it 😌

2.3.2. Browser Behavior and Processing ✨

okay so browsers have to act the same way every time, bestie, or the whole security thing falls apart 🫢 that's the vibe here. if an X-Frame-Options header says "no framing," the user agent of the browser MAY immediately stop downloading or parsing the document πŸ›‘

2.3.2.1. Violation of X-Frame-Options 🚨

when a browser realizes that content with an X-Frame-Options header is about to show up in a frame even though the header said no, it SHOULD redirect to a "NOFRAME" page as soon as possible πŸ’… for example, that could be a noframe.html page that also shows the full URL and hostname of the protected page. iconic move, honestly πŸ™ˆ

the NOFRAME page could also give the user a button to open the target URL in a new window ✨

implementations are kinda all over the place on this one 😭 some browsers show a message so the user can safely open the target page in a new window, and other ones just render an empty frame πŸ’€

2.3.2.2. Variation in Current Browser Behavior 🌈

ngl, the browsers aren't fully on the same page with X-Frame-Options yet 😭 not every browser supports the "ALLOW-FROM" option. it started as an Internet Explorer extension, and at the time of writing, other user agents still haven't implemented it uniformly πŸ₯²

the SAMEORIGIN (and ALLOW-FROM) directive also doesn't get checked the same way everywhere πŸ‘€ the known implementations in Appendix A check SAMEORIGIN by comparing the origin of the framed page with the top-level browsing context. other implementations might compare it with the framed page and the framing page instead, or with the whole chain of nested frames in between 🌸

so what's the difference between the "framing page" and the "top-level browsing context"? picture this: web pages can embed frames with other pages, and those pages can embed frames too, and so on πŸͺ† in theory, you can get infinite nesting of framed pages. for example, web page A can contain web page B in a frame, and web page B can contain web page C in a frame.

Web page A <html> .... <frame src="https://URI_of_web_page_B" /> </html> Web page B <html> .... <frame src="https://URI_of_web_page_C" /> </html> and so forth.

ok so in that setup, when we look at the innermost web page C, the outermost web page A is the "top-level browsing context," and web page B is the "framing page" 🧚

all these different evaluation habits make the header less reliable to use, and they have security implications too, which we'll get into in Section 4 πŸ₯Ί the good news is that a revised version of X-Frame-Options, a Frame-Options directive in CSP 1.1 [CSP-1-1], will unify the behavior, and newer implementations are expected to use that instead of the mechanisms documented here ✨

2.3.2.3. Usage Design Pattern and Example Scenario for the ALLOW-FROM Parameter 🧩

the "ALLOW-FROM" field only supports one serialized-origin 😀 so if a server wants more than one resource to be able to frame its content, this design pattern can get the job done:

  1. a page that wants to show the requested content in a frame passes its own origin information to the server providing that content, using a query string parameter πŸ“¬
  2. the server checks that the hostname meets its criteria, so the page is allowed to frame the target resource πŸ•΅οΈβ€β™€οΈ this could happen by looking up a whitelist of trusted domain names that are allowed to frame the page. for example, for a Facebook "Like" button, the server can check that the supplied hostname matches the hostname(s) expected for that "Like" button πŸ‘
  3. the server returns the hostname in X-Frame-Options: ALLOW-FROM if the criteria were met in step #2 βœ…
  4. the browser enforces the X-Frame-Options: ALLOW-FROM header πŸ›‘οΈ

2.3.2.4. No Caching of the X-Frame-Options Header πŸ™…β€β™€οΈ

caching the X-Frame-Options header for a resource is not recommended, and here's why πŸ“

  1. every http-request for the resource means the browser has to check whether the X-Frame-Options header has been set and act accordingly, because a resource might be created dynamically and the header could change along with it πŸ”„
  2. as explained in Section 2.3.2.3, servers may generate X-Frame-Options header responses depending on the request 🀯 for example, since the ALLOW-FROM directive only has one serialized-origin, imagine a user with several tabs open, where web page 1 is from domain A and web page 2 is from domain B, and both frame the same page from domain C using the ALLOW-FROM directive. in that case, the page has to reply to both requests with different X-Frame-Options headers: the first pointing to origin A, and the second pointing to origin B πŸ˜΅β€πŸ’«

still, we found that none of the major browsers listed in Appendix A cache the responses πŸ’œ


3. IANA Considerations 🧾

IANA has added the specified HTTP header to the "Permanent Message Header Field Name" registry, following "Registration Procedures for Message Header Fields" [RFC3864] πŸ“’

3.1. Registration Template πŸŽ€

Permanent Message Header Field Names Template:

Header field name: X-Frame-Options

Applicable protocol: http [RFC2616]

Status: Informational

Author/change controller: IETF

Specification document(s): RFC 7034

Related information: None

4. Security Considerations 🚨🚨

the X-Frame-Options HTTP header field really does improve protection against clickjacking πŸ™Œ but it is not self-sufficient enough to protect against every kind of these attack vectors, bestie 😬 it must be used together with other security measures, like secure coding (for example, input validation and output encoding) and the Content Security Policy version 1.0 [CSP] πŸ”

it's super important to know that current implementations do not check the origins of the framing resource's entire ancestor tree of frames, and that can expose the resource to attack in multiple-nested scenarios 😱 this is the part where you really need to pay attention 🚩

the browser implementations evaluate based on the origin of the framed page and the top-level browsing context (that is, the most outer frame) πŸͺž

if a resource from origin A embeds untrusted content from origin B, that untrusted content can embed another resource from origin A with an X-Frame-Options: SAMEORIGIN policy, and that check would pass when the user agent only verifies the top-level browsing context πŸ’€ so web developers should be aware that embedding content from other sites can leave their web pages open to clickjacking, even when the X-Frame-Options header is used 🫠

also, X-Frame-Options must be sent as an HTTP header field, and it is explicitly ignored by user agents when it's declared with a meta http-equiv tag 🚫

4.1. Privacy Considerations πŸ•ΆοΈ

there are two kinds of potential data leakage to think about πŸ‘€

  1. using X-Frame-Options with the ALLOW-FROM parameter lets a page guess or infer information about who is framing it πŸ” a web server can answer requests with the X-Frame-Options: ALLOW-FROM header and figure out which other page is framing it. this is inherent by design, but it can lead to data-leakage or data-protection concerns 😬
  2. a web server using the ALLOW-FROM directive effectively discloses the origin specified in the header πŸ“£ if a web server wants to reduce this leakage, it is recommended to generate the ALLOW-FROM header for each request, based on the design pattern described in Section 2.3.2.3 πŸ’–

5. References πŸ“š

5.1. Normative References

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119, March 1997.

[RFC3986]  Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
           Resource Identifier (URI): Generic Syntax", STD 66,
           RFC 3986, January 2005.

[RFC5234]  Crocker, D. and P. Overell, "Augmented BNF for Syntax
           Specifications: ABNF", STD 68, RFC 5234, January 2008.

[RFC6454]  Barth, A., "The Web Origin Concept", RFC 6454,
           December 2011.

5.2. Informative References

[CLICK-DEFENSE-BLOG]
           Lawrence, E., "IE8 Security Part VII: Clickjacking
           Defenses", Microsoft Developer Network Blogs,
           January 2009, <http://blogs.msdn.com/b/ie/archive/2009/01/
           27/ie8-security-part-vii-clickjacking-defenses.aspx>.

[CSP]      Sterne, B. and A. Barth, "Content Security Policy 1.0",
           W3C Candidate Recommendation CR-CSP-20121115,
           November 2012,
           <http://www.w3.org/TR/2012/CR-CSP-20121115/>.

[CSP-1-1]  Barth, A. and M. West, "Content Security Policy 1.1", W3C
           Working Draft WD-CSP11-20130604, June 2013,
           <http://www.w3.org/TR/2013/WD-CSP11-20130604/>.

[CSRF]     OWASP (Open Web Application Security Project), "Top-10
           2013-A8-Cross-Site Request Forgery (CSRF)", June 2013,
           <https://www.owasp.org/index.php/
           Top_10_2013-A8-Cross-Site_Request_Forgery_%28CSRF%29>.

[Clickjacking]
           OWASP (Open Web Application Security Project),
           "Clickjacking", April 2013,
           <http://www.owasp.org/index.php/Clickjacking>.

[FRAME-BUSTING]
           Stanford Web Security Research, "Busting frame busting: a
           study of clickjacking vulnerabilities at popular sites",
           July 2010,
           <http://seclab.stanford.edu/websec/framebusting/>.

[HTTPbis-P1]
           Fielding, R. and J. Reschke, "Hypertext Transfer Protocol
           (HTTP/1.1): Message Syntax and Routing", Work in Progress,
           September 2013.

[Microsoft-X-Frame-Options]
           Lawrence, E., "Combating ClickJacking With X-Frame-
           Options", Microsoft Developer Network Blogs, March 2010,
           <http://blogs.msdn.com/b/ieinternals/archive/2010/03/30/
           combating-clickjacking-with-x-frame-options.aspx>.

[Mozilla-X-Frame-Options]
           Mozilla Developer Network, "The X-Frame-Options response
           header", August 2013, <https://developer.mozilla.org/
           en-US/docs/The_X-FRAME-OPTIONS_response_header>.

[RFC2616]  Fielding, R., Gettys, J., Mogul, J., Frystyk, H.,
           Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext
           Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.

[RFC3864]  Klyne, G., Nottingham, M., and J. Mogul, "Registration
           Procedures for Message Header Fields", BCP 90, RFC 3864,
           September 2004.

[RFC6648]  Saint-Andre, P., Crocker, D., and M. Nottingham,
           "Deprecating the "X-" Prefix and Similar Constructs in
           Application Protocols", BCP 178, RFC 6648, June 2012.

Appendix A. Browsers That Support X-Frame-Options 🌟

  • Internet Explorer 8+
  • Firefox 3.6.9+
  • Opera 10.5+
  • Safari 4+
  • Chrome 4.1+

Appendix B. Description of a Clickjacking Attack 🎣

okay, the fun part is coming up πŸ’œ a more detailed explanation of clickjacking scenarios follows πŸ¦‹

B.1. Shop

An internet marketplace or online shop has a feature with a "Buy this" link or button. They want their affiliates, who could be malicious attackers, to be able to drop "Buy such and such from XYZ" IFRAMES into their pages. That opens a possible clickjacking threat 😬. So the marketplace/online shop needs to immediately send the main browsing context (or a new window) to a confirmation page that has anti-clickjacking protections.


B.2. Online Shop Confirm Purchase Page

The "Confirm Purchase" page of an online shop has to be shown to the end-user without any risk of an overlay or misuse by an attacker πŸ›οΈ. That's why this page combines anti-CSRF tokens (Cross Site Request Forgery [CSRF]) with the X-Frame-Options HTTP header field. Together they help mitigate clickjacking attacks. Bestie, that's a really solid combo πŸ’…βœ¨


B.3. Flash Configuration

Macromedia Flash configuration settings get set by a Flash object πŸŽ€. That object can only run from one specific configuration page on Macromedia's site. It runs inside the page, so it can be subject to a clickjacking attack πŸ™ˆ. To stop clickjacking from messing with the security settings, the configuration page uses the X-Frame-Options directive.


Appendix C. Acknowledgements 🫢

This document was derived from input from specifications published by various browser vendors, such as Microsoft (Eric Lawrence and David Ross), Mozilla, Google, Opera, and Apple 🌈 Huge thank-yous to all of them, they're absolutely iconic πŸ‘‘


Authors' Addresses πŸ’œ

David Ross Microsoft

EMail: dross@microsoft.com

Tobias Gondrom Thames Stanley

EMail: tobias.gondrom@gondrom.org

πŸ“¦ where this page comes from