Tabnabbing Attacks and Prevention
Tags: security, webdev, cybersecurity, programming
Published: 2021-04-06 17:00:43

## What are tabnabbing attacks?

Tabnabbing attacks enable a malicious website to suddenly redirect a legitimate page to the attacker's page.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eirlght6zvyw6qrkp6at.gif)

They can be an effective tool in phishing attacks, so let's see how you as a developer can safeguard your users against the attack.

Let's first look at the different forms of tabnabbing and then we'll discuss the defenses. You will get to play with interactive demos throughout this article, or just watch them in animated GIFs if that's your preference.

The original article can be found [here](https://www.appsecmonkey.com/blog/tabnabbing).

## A hole in the Same Origin Policy

Before we proceed, I should say two words about the same-origin policy.

For the sake of this article, it is enough for you to know that the same-origin policy is the browser security mechanism that isolates different websites from each other.

It ensures that, e.g., google.com cannot read your Facebook feed, even though you have Google and Facebook open in the same browser.

And while the same-origin policy restricts many things, it has many "holes" because websites do need to interact with each other to some extent.

And the hole that we are most interested in right now is the following:

1. If websites A and B are from different origins
2. And website A manages to get a window handle to website B
3. Then website A is allowed to redirect website B's window to any URL address at any given time

This hole is the reason tabnabbing attacks exist, as you'll soon see.

If you want to learn more about the same-origin policy, we have an in-depth article right [here](https://appsecmonkey.com/blog/same-origin-policy).

## How do tabnabbing attacks work?

There are a couple of ways in which a malicious website could get the window handle to your website. These are the most common.

### 1. Tabnabbing by the malicious page opening a window

Perhaps the easiest and most reliable way for another website to get a window handle to your website's window is for the malicious website to open it via `window.open` like so.

```js
var windowHandle = window.open('https://goodsite.example')
// sleep for some time, and suddenly...
windowHandle.location.replace('https://hacked.example')
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eirlght6zvyw6qrkp6at.gif)

### 2. Reverse tabnabbing by the good site opening a window

Another possibility is the other way around, that is, your website opens the malicious website via `window.open` like so:

```js
window.open('https://evil.example')
```

The malicious website can then get a window handle to your website via the `window.opener` property like so:

```js
window.opener.location.replace('https://hacked.example')
```

### 3. Reverse tabnabbing via links

The second reverse tabnabbing variant is if you link to a malicious/compromised website with a `target="_blank"` so that the website will open in a new tab/window. In this case, the linked website can refer to the previous window via `window.opener`.

```js
window.opener.location.replace('https://hacked.example')
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lzor1qt97ytsekj6rov8.gif)

### 4. Reverse tabnabbing via frames

The third reverse tabnabbing method is if your website loads another website in an `IFRAME`. For example, advertisements can work this way. In this case, the malicious website in the frame can get a window handle to the parent window using the `window.parent` property like so:

```js
window.parent.location.replace('https://hacked.example')
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/14wlr2n3z4t3cs4d1mti.gif)

### Try it!

Play around with the attacker's page [here](https://uw55c.csb.app/) and the "good page" [here](https://igqf9.sse.codesandbox.io/).

I should mention that depending on your browser and configuration, the attacks might not work. We'll get to why at the end of this article. Just don't be surprised if that happens to you now.

It's also worth noting that if the CodeSandbox instances were hibernated, you might want to refresh the pages after waking up the applications to ensure that everything works as expected.

## How to prevent tabnabbing attacks?

Preventing tabnabbing attacks is relatively straightforward.

1. Implement a cross-origin opener policy
2. Set the rel="noopener" attribute to your links
3. Sandbox your frames
4. Implement an isolation policy

### Implement a cross-origin opener policy

There is a relatively new browser security feature called `Cross-Origin Opener Policy`. You can use COOP to prevent the attack where a malicious website calls `window.open` on your website and then sneakily redirects the user into the attacker's page.

Just return the following HTTP response header from your webserver. The browsers that support COOP will process-isolate your document, and potential attackers can't access your window anymore.

```yaml
Cross-Origin-Opener-Policy: same-origin
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/892p6pm7if21qeglv3u9.gif)

Additionally, windows that _your website_ opens via `window.open()` will not be able to attack you anymore.

The cross-origin opener policy feature is (at the time of this writing) already supported by Firefox, Chrome, and Edge, but not by Safari or IE. You can check the up-to-date status [here](https://appsecmonkey.com/browser-support/cross-origin-opener-policy).

Read more about COOP [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy).

### Set the rel="noopener" attribute to your links

You can link to other websites in new windows as long as you include the `rel="noopener"` attribute in the `a`-tag. Like so.

```html
<a href="https://www.example.com" rel="noopener noreferrer"></a>
```

I added the `noreferrer` as a bonus because it's a good practice to add even though it's not related to tabnabbing attacks. The `noreferrer` will prevent information from the browser user's URL from leaking to the other website in the `Referrer`-header. You can read more about that [here](https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/noreferrer).

The `noopener` attribute is the crucial part here. It tells browsers not to give the link target a handle to your website's window by setting the `window.opener` to `null`.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yr26x6xxniycoasltt75.gif)

You can read more about the `noopener` attribute [here](https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/noopener).

### Sandbox your frames

To prevent tabnabbing attacks from websites that you load in an iframe, all you need to do is _sandbox_ the frame. Sandboxing is facilitated with the `sandbox` attribute like so:

```html
<iframe sandbox="allow-scripts allow-same-origin" src="https://www.example.com"></iframe>
```

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wyo7f0i5jfry86ouc89w.gif)

By default, the `sandbox` attribute limits many things. Most importantly, it **prevents the content from navigating its top-level browsing context**, that is, it stops the framed website from redirecting its parent.

However, it also blocks things like having an origin at all or executing scripts. In the example above, we granted those two so that the frame can operate as expected.

### Implement an isolation policy with fetch metadata

Another relatively recent browser security feature is _fetch metadata_. It allows you to block HTTP requests on the server-side if they originate from unwanted websites or happen in suspicious contexts.

Isolation policies are an insanely effective security control against a multitude of cross-site/cross-window attacks. While it's [not yet supported](https://appsecmonkey.com/browser-support/fetch-metadata) by Firefox or Safari, you can implement such a policy in a fully backward compatible manner and reap the benefits on the browsers that do support it.

I won't go into too much detail about isolation policies in this article. You can read a thorough treatment about them in [this article](https://appsecmonkey.com/blog/fetch-metadata) which also features a complete example that you can run on CodeSandbox.

### Try it!

Play around with the attacker's page [here](https://uw55c.csb.app/) and the COOP-protected test page [here](https://3xwfj.sse.codesandbox.io/).

## Browsers try to fight tabnabbing

Modern browsers try to implement heuristics and better defaults to combat tabnabbing attacks.

For example, most browsers these days treat links that have `target="_blank"` as `rel="noopener"` by default unless you explicitly specify something else.

On Firefox the feature is enabled as long as you have `dom.targetBlankNoOpener.enabled` enabled in <a href="about:config">about:config</a>. Read about it [here](https://bugzilla.mozilla.org/show_bug.cgi?id=1522083).

Chrome also has the same feature which you can read about [here](https://www.chromestatus.com/feature/6140064063029248).

Ditto for [Safari](https://webkit.org/blog/8475/release-notes-for-safari-technology-preview-68/).

Also, browsers might prevent redirections or popups that appear suspicious or ask the user if they want to allow them.

However, you can't rely on the browser to keep your web application safe. Most of the attacks are not prevented out-of-the-box.

## Conclusion

Tabnabbing attacks can be a severe threat, especially when used as part of a targeted phishing attack. Luckily there are simple steps that you can take to protect your web application from them:

1. Implement a cross-origin opener policy
2. Add the `rel="noopener"` attribute to the links on your website.
3. Add the `sandbox` attribute to iframes on your website.
4. Implement an isolation policy with fetch metadata.

Additionally, browsers are getting smarter in preventing tabnabbing attacks. Still, they're not quite there yet, so you as the developer will have to take care of implementing these security controls to protect your users.

## Get the web security checklist spreadsheet!
[![Subscribe](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3iqd1ef4a5a0icyvvk65.jpg)](https://eepurl.com/hqAGt5)
 ☝️ [Subscribe](https://eepurl.com/hqAGt5) to AppSec Monkey's email list, get our best content delivered straight to your inbox, and <b>get our 2021 Web Application Security Checklist Spreadsheet for FREE</b> as a welcome gift!

## Don't stop here
If you like this article, check out the other application security guides we have on [AppSec Monkey](https://www.appsecmonkey.com/) as well.

Thanks for reading.