Reputation: 38400
Why are iframes considered dangerous and a security risk? Can someone describe an example of a case where it can be used maliciously?
Upvotes: 188
Views: 196765
Reputation: 9926
When you "use iframes", it doesn't just mean one thing. It's a lexical ambiguity. Depending on the use case, "using iframes" may mean one of the following situations:
1. Someone else displays your content (e.g. your site is running in iframe)
This is not "you using iframes", it's "them using iframes". Not your call. It's used for deception, yes, but it has nothing to do with you using iframes in your own code or not. Someone else showing your site, or something that looks like your site, can happen, it can be done a couple of other ways too. I've heard IT experts saying "avoid iframes because then your site can be clickjacked" - it's like not buying a camera to prevent others taking photos of you. Makes no sense.
2. You display someone else's content
Of the three above, this is the only one that's somewhat risky, but most of the scary articles you read all the time come from a world before same-origin policy was introduced. Right now, it's still not recommended to include just any site into your own (who knows what it will contain tomorrow?), but if it's a trusted source (accuweather, yahoo stock info etc), you can safely do it. The big no-no here is letting users (therefore, malicious users) control the src
of the iframe, telling it what to display. Don't let users load arbitrary content into your page, that's the root of all evil. But it's true with or without iframes. It has nothing to do with them; it could happen using a script
or a style
tag (good luck living without them) - the problem is you let them out. Any output on your site containing any user-given content is RISKY. Without sanitizing (de-HTMLifying) it, you're basically opening your site up for XSS attacks, anyone can insert a <script>
tag into your content, and that is bad news. Like, baaaad news.
Never output any user input without making dead sure it's harmless.
So, while iframes are innocent again, the takeaway is: don't make them display 3rd-party content unless you trust the source. In other words, don't include untrusted content in your site. (Also, don't jump in front of fast-approaching freight trains. Duuh.)
3. You display your own content in an iframe
This one is obviously harmless. Your page is trusted, the inner content of the iframe is trusted, nothing can go wrong. Iframe is no magic trick; it's just an encapsulation technique, you absolutely have the right to show a piece of your content in a sandbox. It's much like putting it inside a div or anything else, only it will have its own document environment.
UPDATE:
For case 2, there is an attribute called sandbox, worth checking out: https://www.w3schools.com/tags/att_sandbox.asp
Upvotes: 27
Reputation: 15935
The IFRAME
element may be a security risk if your site is embedded inside an IFRAME
on hostile site. Google "clickjacking" for more details. Note that it does not matter if you use <iframe>
or not. The only real protection from this attack is to add HTTP header X-Frame-Options: DENY
and hope that the browser knows its job.
If anybody claims that using an <iframe>
element on your site is dangerous and causes a security risk, they do not understand what <iframe>
element does, or they are speaking about possibility of <iframe>
related vulnerabilities in browsers. Security of <iframe src="...">
tag is equal to <img src="..."
or <a href="...">
as long there are no vulnerabilities in the browser. And if there's a suitable vulnerability, it might be possible to trigger it even without using <iframe>
, <img>
or <a>
element, so it's not worth considering for this issue.
In addition, IFRAME element may be a security risk if any page on your site contains an XSS vulnerability which can be exploited. In that case the attacker can expand the XSS attack to any page within the same domain that can be persuaded to load within an <iframe>
on the page with XSS vulnerability. This is because vulnerable content from the same origin (same domain) inside <iframe>
is allowed to access the parent content DOM (practically execute JavaScript in the "host" document). The only real protection methods from this attack is to add HTTP header X-Frame-Options: DENY
and/or always correctly encode all user submitted data (that is, never have an XSS vulnerability on your site - easier said than done).
However, be warned that content from <iframe>
can initiate top level navigation by default. That is, content within the <iframe>
is allowed to automatically open a link over current page location (the new location will be visible in the address bar). The only way to avoid that is to add sandbox
attribute without value allow-top-navigation
. For example, <iframe sandbox="allow-forms allow-scripts" ...>
. Unfortunately, sandbox also disables all plugins, always. For example, historically Youtube couldn't be sandboxed because Flash player was still required to view all Youtube content. No browser supports using plugins and disallowing top level navigation at the same time. However, unless you have some very special reasons, you cannot trust any plugins to work at all for majority of your users in 2021, so you can just use sandbox
always and guard your site against forced redirects from user generated content, too. Note that this will break poorly implemented content that tries to modify document.top.location
. The content in sandboxed <iframe>
can still open links in new tabs so well implemented content will work just fine. Also notice that if you use <iframe sandbox="... allow-scripts allow-same-origin ..." src="blog:...">
any XSS attack within the blob:
content can be extended to host document because blob:
URLs always inherit the origin of their parent document. You cannot wrap unfiltered user content in blob:
and render it as an <iframe>
any more than you can put that content directly on your own page.
Example attack goes like this: assume that users can insert user generated content with an iframe; an <iframe>
without an attribute sandbox can be used to run JS code saying document.top.location.href = ...
and force a redirect to another page. If that redirect goes to a well executed phishing site and your users do not pay attention to address bar, the attacker has a good change to get your users to leak their credentials. They cannot fake the address bar but they can force the redirect and control all content that users can see after that. Leaving allow-top-navigation
out of sandbox
attribute value avoids this problem. However, due historical reasons, <iframe>
elements do not have this limitation by default, so you'll be more vulnerable to phishing if your users can add <iframe>
element without attribute sandbox
.
Note that X-Frame-Options: DENY
also protects from rendering performance side-channel attack that can read content cross-origin (also known as "Pixel perfect Timing Attacks").
That's the technical side of the issue. In addition, there's the issue of user interface. If you teach your users to trust that URL bar is supposed to not change when they click links (e.g. your site uses a big iframe with all the actual content), then the users will not notice anything in the future either in case of actual security vulnerability. For example, you could have an XSS vulnerability within your site that allows the attacker to load content from hostile source within your iframe. Nobody could tell the difference because the URL bar still looks identical to previous behavior (never changes) and the content "looks" valid even though it's from hostile domain requesting user credentials.
Update year 2023:
Content-Security-Policy (CSP) supports directive frame-ancestors
which will override the non-standard de-facto header X-Frame-Options: deny
.
As a result, you could emit both X-Frame-Options: deny
and Content-Security-Policy: frame-ancestors none
to block click jacking attacks for both old and modern user agents / internet browsers.
In practice, all browsers that do not natively support CSP directive frame-ancestors
are probably old enough to have at least one critical security vulnerability so you can stop serving X-Frame-Options: deny
if you define policy for header Content-Security-Policy
directive frame-ancestors
. (Browsers with critical vulnerabilities are not safe to use no matter what headers you emit.)
Upvotes: 193
Reputation: 3308
I'm assuming cross-domain iFrame since presumably the risk would be lower if you controlled it yourself.
Upvotes: 21
Reputation: 114367
As soon as you're displaying content from another domain, you're basically trusting that domain not to serve-up malware.
There's nothing wrong with iframes per se. If you control the content of the iframe, they're perfectly safe.
Upvotes: 129