Omri
Omri

Reputation: 915

Content-Security-Policy (CSP) frame-ancestors for iframes without src

I want to prevent hosting my website (i.e., www.my.com) in an iframe except for an allow-list of domains (i.e., www.test.com, www.bla.com, ..., www.n.com) to protect against clickjacking.

To implement it for normal browsers I use Content-Security-Policy and send all the domains with both http and https schema. for IE I use the referrer hostname and check it against the allow-list of domains; if the domain exists, I add it to X-Frame-Options; otherwise, I send SAMEORIGIN. For example, assuming the referrer domain is www.n.com

X-Frame-Options: ALLOW-FROM https://www.n.com

Content-Security-Policy: frame-ancestors 'self' https://www.test.com https://www.bla.com ... https://www.n.com; http://www.test.com http://www.bla.com ... http://www.n.com;

However, I want to host my website inside an other website (salesforce in this case) and this website doesn't host the iframe directly in the top page, but creates another iframe without a URL (i.e., without the src attribute) and host my iframe inside:

-> top window: www.n.com
-> -> iframe without src <iframe name="some_name">
-> -> -> iframe with my website <iframe src="https://www.my.com">

The browser (chrome) prevents my website from loading since: "Refused to frame 'https://www.my.com/' because an ancestor violates the following Content Security Policy directive...".

I think it includes the middle iframe (without the src) in the CSP check and that is the problem.

How can I protect my website from clickjacking using the Content-Security-Policy / X-Frame-Options while supporting this situation?

UPDATE If you are reading this question - I found that chrome ignores the empty src and works as expected. I was wrong and missed another domain in the way:

-> top window: www.n.com
-> -> iframe with some src <iframe src="https://www.opppsss.com">
-> -> -> iframe without src <iframe name="some_name">
-> -> -> -> iframe with my website <iframe src="https://www.my.com">

You need to add all of the domains in the chain to the CSP header.

Upvotes: 0

Views: 8261

Answers (2)

granty
granty

Reputation: 8546

The frame-ancestors directive works with tuple of origins.

  • In case of <iframe src=http://... things is easy and tuple of origin is taken from the src=.

  • In case of <iframe src=data:-Url the origin will be opaque, therefore frame-ancestors skips it and checks the parent.

  • In case of <iframe name="some_name"> its content is created by parent page javascript using .contentDocument property. So the origin of the iframe will be the same as the parent page.

Therefore you must specify in the frame-ancestors the origins of the entire ascending chain of parents in the DOM.
Unfortunately, the X-Frame-Options:... header is not suitable in case of several host-sources.

The browser (chrome) seems to include the middle iframe in the CSPv check and prevents my website from loading.

Its very interesting how did you know that...
IMHO the problem is your CSP is based on referrer. Which referrer you expect to get in case of:

-> top window: www.n.com
-> -> iframe without src <iframe name="some_name">
-> -> -> iframe with my website <iframe src="https://www.my.com">

I think you have got empty referrer taken from nearest parent, therefore is published Content-Security-Policy: frame-ancestors 'self' -> embedding into salesforce is forbidden.

Upvotes: 1

Halvor Sakshaug
Halvor Sakshaug

Reputation: 3465

Content-Security-Policy frame-ancestors can contain multiple sources, so you can include your entire allow-list. As all ancestors need to pass the frame-ancestors check you must include multiple sources for your salesforce example to work, see https://www.w3.org/TR/CSP3/#frame-ancestors-navigation-response

X-Frame-Options ALLOW-FROM can only contain one source, and it is up to the browser to decide if the all ancestors, top or bottom must match, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options.

Upvotes: -1

Related Questions