Hacker News new | comments | show | ask | jobs | submit login
Target="_blank" – An underestimated vulnerability (2016) (jitbit.com)
264 points by handpickednames 11 months ago | hide | past | web | favorite | 58 comments

I think/hope Chromium's recent announcement about "Expanding user protections on the web", addresses the redirect issue:

> When the user interacts with content, things can also go wrong. One example that causes user frustration is when clicking a link opens the desired destination in a new tab, while the main window navigates to a different, unwanted page. Starting in Chrome 65 we'll also detect this behavior, trigger an infobar, and prevent the main tab from being redirected. This allows the user to continue directly to their intended destination, while also preserving the context of the page they came from.


Excellent! Stealth redirects and vibrating ads are what drove me to Firefox for Android with uBlock.

Note that developers could protect their sites for some time with noopener: https://mathiasbynens.github.io/rel-noopener/

Vibrating ads as in they move around or they cause your phone to vibrate? Never seen that, but either way that makes me all the more glad to have ad blocking installed at the root level. The level of annoyance the ad industry goes to is astounding.

They cause my phone to vibrate "thanks to" the Vibration API [0]. A critical component of the Web Platform ecosystem apparently.

[0]: https://developer.mozilla.org/en-US/docs/Web/API/Vibration_A...

In time this annoyance API will be seen as equivalent to the blink [1] tag.

[1] https://en.wikipedia.org/wiki/Blink_element

Seems very inappropriate to even allow this. It would be like allowing the page to activate your flashlight. Wtf... shouldn't allow hardware access like that.

yay! fucking retailmenot does this big time!

Various articles, blog posts etc. about this have already been posted to HN.

One of these inspired me to make a Firefox add-on that solves this issue: https://addons.mozilla.org/en-US/firefox/addon/dont-touch-my... [/plug]

Still always good to keep in people's minds.

Personally I use linting rules for this, e.g. for React projects https://github.com/yannickcr/eslint-plugin-react/blob/master...

Google considers (1) it unfixable:

"Unfortunately, we believe that this class of attacks is inherent to the current design of web browsers and can't be meaningfully mitigated by any single website; in particular, clobbering the window.opener property limits one of the vectors, but still makes it easy to exploit the remaining ones."

(1) https://sites.google.com/site/bughunteruniversity/nonvuln/ph...

Lighthouse Audit - Opens External Anchors Using rel="noopener": https://developers.google.com/web/tools/lighthouse/audits/no...

The 'popular' eslint-plugin-react can also make this a lint error https://github.com/yannickcr/eslint-plugin-react/blob/master...

Couldn't `window.opener` be opt-in instead of opt-out? It would break some websites, but I have no idea how many...

Whilst they might not consider it fixable, that doesn't mean they're not going to do the best they can!

Chrome does support rel=noopener, _and_ the "fairly good demonstration" that page links to doesn't work in Chrome any more.


What are the remaining vectors which would need to be mitigated? The Google article does not mention any details?

One is that if you open a window, you can change the URL that's loaded later.

In the example that Google's page links to they change it to a data: URI - which no longer works in Chrome - but they could just as easily change it from http://good.com/ to http://evil.com/ - which would still work in Chrome - and hope you don't notice.

But how can they do that without access to `window.opener`?

In the example, a nefarious page opens a new window and then uses its connection to that opened window - the window object is returned from "window.open()" - to manipulate it. No window.opener required, and the two windows don't even need to be in the same website for this to work.

Google's page isn't just about abusing "window.opener", it's generally about abusing JavaScript-accessible connections between windows/tabs. Additionally, the site it's in isn't about browser bugs, but bugs in Google's websites. Google knows these issues are fixable, but they consider them to be flaws in browsers rather than in their websites.

That's why Google says it's still easy to exploit the other vectors for the attack. A website can protect itself by clearing "window.opener", but similar attacks are possible that a website can't prevent. e.g. A window can't prevent the window that opened it from later forcing it to navigate to a different URL.

In Opera 12, I killed "window.opener" by replacing the "opener" string with "opera" in the opera.dll. This way it gets overwritten by the normal window.opera variable and is essentially hidden. So far I haven't encountered a site legitimately relying on this variable.

Admirably thuggish! I remember doing something similar, replacing "__gnu_warning" with "__gnu_whining" in libc.so to eliminate whining about using "gets()" in throwaway programs.

Window.opener isn’t your problem. Window.opener is sandboxed by CORS. And you need it for things such as oAuth.

Target=“_blank” is your problem. That’s where Window.opener gets exposed. You’re better off finding the “_blank” definition and renaming it so that it’s never triggered, or assigning it to the definition of “self”, etc.

Killing off "_blank" would disable force-opening links in a new window, which is useful in dynamic context, e.g. chat page, so I don't want that.

Also, window.opener is still abusable if I middle-click links to open in a new tab. I was very surprised when my Google Search tab got replaced by something else after I middle-clicked on some questionable link.

A legitimate usage case would be opening a login popup on another domain that can't be iframe'd. For example OAuth social network login popups. They require window.opener to send back login credentials to the original website.

It's crazy that, after 20 years, web standards people still haven't realized that the server is the user's enemy. Back in the 90s, this was demonstrated by popups, which eventually got mostly fixed in most browsers. Now we have this new pop-under mechanism, currently marked as WONTFIX, which will get slowly mitigated over the next few years. Window.opener and target=_blank are obvious avenues of abuse that would never have been added if web people had learned anything over the past couple of decades.

Didn't target="_blank" originate in that era you were talking about? I know the target attribute was part of HTML4 (1999). I'm not sure when _blank became a special value, but I imagine it was before the spec acknowledged it.

I agree window.opener was a fairly dangerous addition, but it is subject to CORS restrictions. You can't access it from just anywhere.

I think you're right about target=_blank. Still, it has very little potential to benefit the user, who can option-click or similar if he/she wants a new tab or window, but has to copy-and-paste to prevent one. It should never have been added.

I would rather that web browsers simply not implement things with significant potential to do harm; at the least, those things should be disabled by default. Unfortunately we aren't headed that way: WebUSB is coming[1]. Anyone who could write that "[t]he composablity of the web allows a new ecosystem of hardware support to be built entirely from web technology" without feeling a chill run down their spine and imagining a years-long security nightmare is truly blind.

[1] https://wicg.github.io/webusb/

Strewth, I can't even read that without wanting to go and uninstall every browser from every device I own.

Are people really considering this? People that, y'know... matter?

edit: good lord, I read further and saw this:

    3. Security and Privacy
    This section is non-normative.
...I mean... surely, surely that's the one bit that should be most gigantically normative? Right?

"This specification recommends device manufacturers practice defense in depth by designing their devices to only accept signed firmware updates and/or require physical access to the device in order to apply some configuration changes."

Yes, let's put the burden of protecting users from browser-transmitted malware on to the hardware manufacturers, who've had a such a wonderful track record of caring about and protecting their users' security in the past. What could possibly go wrong?

Aagh! "Let's take hardware designed to be connected to a machine by its owner, connect it to the whole internet, and blame the hardware when it gets hacked." Does anyone remember how long it took for single-user operating systems to harden themselves against remote attacks? Yeah, they're still working on it. Now imagine something like that, but for hardware that either never gets firmware updates, or is connected to the internet so it can have them pushed.

> ...I mean... surely, surely that's the one bit that should be most gigantically normative? Right?

No. "Security and privacy considerations" sections of standards documents are typically used for a analysis or discussion of the security/privacy posture of the standard. The security features are "baked into" other portions of the document.

> I agree window.opener was a fairly dangerous addition, but it is subject to CORS restrictions. You can't access it from just anywhere.

You can't access things via opener but you can change the location of opener, that's an easy target for phishing.

> the server is the user's enemy

Not that much. Both have some conflicting interests, and plenty of aligned interests.

Setting target=_blank is almost always a bad idea anyway. Typically marketers ask for it to prevent users from leaving your domain when clicking a link to an external domain; the thinking being they will remain on our site longer if we force a new window on them.

Testing has shown that this doesn't work in practice, and instead achieves the opposite: the user in confused as to why they are in a new window, and it's harder for them to return to your domain. The user is confused by the ostensible "pop-up" (that they associate with ads) that has opened, and the Back button no longer returns them to our domain, breaking with their expected behavior.

Users know how to open links in new tabs/windows if they want to. In testing at the places I've worked target=_blank only hurts conversions. Personally I run a plugin that strips it from all links.

'Testing has shown that this doesn't work in practice....'

Is there any research you can point me to about this?

'...and the Back button no longer returns them to our domain, breaking with their expected behavior.'

Yeah, except when the target site has disabled it and then you have even more confusion. (Accepted it is rare, but it does happen).

I was referencing internal A/B testing results for several high-volume e-commerce sites I've worked on.

An oft-parroted best practice in UX is "effective user interface places users in control of the application." This study seems to agree:


>Many of our study participants moved to a new site or subsite without realizing it and then struggled to get back to the main site because the subsite offered no option for return

Using target=_blank ensures the Back button is broken. A third-party site disabling the Back button is out of your control.

Thanks for the further information.

In my experience, users who know the Back button exists are already one step ahead. Some users don’t know Back/Forward buttons at all. When they open a link that replaces their current page, they have no idea how to go back; they close this tab, open a new one, uses Google to search for the original page and hope to find it. Furthermore actual pop-up windows are associated with ads but a new tab? Not so much.

Quick fix is _Search and Replace_ in your whole project, via your favourite editor, from,

> target="_blank"


> target="_blank" rel="noopener noreferrer"

Which should not break anything unless you have some weird HTML lying around.

Yep you're right. I wrote a post about it before on Medium and made an extension that automatically puts noreferrer in there for you. Here's the link: https://medium.com/@Jamie_Farrelly/browsers-are-broken-but-n...

Does that also work on the <base> element? Browsing through MDN it seems like it doesn’t.

TL;DR : read the original post, its to the point.

why not make rel="noopener noreferrer" default? if sites want to get credit they can explicitly add rel="opener referrer"

They had their chance with HTML5. Actually, it was removed at some point.

I reckon it should be an optional attribute for the BASE tag, rather than having to add it to every single A tag

Backwards compat

I’ve seen one case, not saying the generic model is not an issue, where this was particularly bad. In a thick client built on web, there was absolutely no indication of redirection because the app’s window showed only content. Plus it was stored and delivered to other users. Persistent open redirect in a thick client.

Once again we have to ask "why is this even possible?" Web designers have been given too much control over the browser is the usual answer and seem to be the case here. There should be no interaction allowed between tabs.

The problem is the implementation, not the feature.

The postMessage API provides a safer way for Windows/Tabs to communicate.


Given that most implementation are flawed, and given the limited utility of this "feature", and given the inherent desire to sandbox thing on a browser, I would say the problem is the mindset of the developers who keep adding stuff that ends up exploited.

Couldn't this just follow same domain rules like CORS?

But yeah it could break a lot of things... changing location is bad, but can it really execute JavaScript in the opener context? That would be very serious.

JavaScript is subject to CORS, but "opener" isn't generally, except in Edge.

Even then, there is a risk of being surprised. If you open a page on the same site, you may expect that scripts on the opened page can't access the opening page: but because of CORS they can.

Here's a fiddle with a link to another fiddle that copies the contents of a password field from the first fiddle: https://jsfiddle.net/u6rmc49c/3/

CORS is only for http requests.

The same origin policy for DOM access allows setting the location.href attribute (getting any attribute is still disallowed). Setting location.href also works with frames in both ways, e.g. frame.location.href as well as parent.locaton.href and top.location.href

This reminds of my 9year old vulnerability reported here: https://bugzilla.mozilla.org/show_bug.cgi?id=469939.

Essentially one can trick a user into typing their credentials into a phishing site although it may appear they are using the legitimate site at first glance.

The reason this is unfixed is that this is how the web works still.

I'm pretty ignorant of browser stuff, but couldn't the attack be even worse than mentioned in the article?

If the newly opened website has full control over the Facebook tab, can't the attacker directly modify the html in the opener to pop up a form asking for a password? This would be stronger because the address would not change.

Could the attacker reach into the Facebook tab and pull any information from it?

No. You do not have access to the contents of the window because facebook.com is on a different origin.

As this article says, you can change the location of the window.

> PS. Interestingly, Google doesn't seem to care.

Doesn't Google's browser hide the address bar !? Hiding the address does make exploits like this way harder to notice. I know Google want's everyone to search instead of typing an URL. But URL's are really powerful, please Google, don't make them irrelevant!

> Doesn't Google's browser hide the address bar

Huh? What are you talking about? All mobile browsers I'm aware of hide the address bar when you scroll down, not just Chrome.

Though when you navigate to a new page the address bar does show as the page loads.

I can assure you that at least "some" people at Google care.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact