• Stars
    star
    140
  • Rank 261,473 (Top 6 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created almost 10 years ago
  • Updated over 5 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Prevent reverse tabnabbing phishing attacks caused by _blank

blankshield

Prevent reverse tabnabbing based phishing attacks that take advantage of _blank targets. Demo. The library has been tested and is compatible with the latest versions of Chrome, Firefox, Safari, Opera, as well as IE6-11. This is a cross-browser solution for browsers that do not support noopener.

Overview

Tabs or windows opened using JavaScript or target="_blank" have some limited access to the parent window, ignoring cross-origin restrictions. Among that is the ability to redirect the parent tab or window using window.opener.location.

While it may seem harmless, a phishing attack is possible when web applications permit or make use of user-submitted anchors with target="_blank" or window.open(). Consider the following scenario:

You're an admin using some forum or chat software. You're currently logged into the app, and view a message left by a user. The user asks or convinces you to click a link in his message, which opens in a new tab. While the new page may look completely safe - perhaps just a screenshot or bug report in some HTML, it executes the following JS:

window.opener.location.assign('https://yourcompanyname.phishing.com');

What you don't realize is that while dealing with this illegitimate customer or user complaint, your application's tab was redirected in the background. To what? An identical phishing website, simply requesting that you enter your credentials to log back in.

Is there a chance you might not check the URL? That you didn't notice the tab icon refresh? While many are suspicious of links they click and new tabs they open - what about existing tabs?

demo

Vulnerable browsers

The following table outlines the scope of affected browsers:

Browser Click Shift + click Meta/Ctrl + click
Chrome 40 x x x
Firefox 34
Opera 26 x x x
Safari 7, 8 x
IE6...11 [1]

[1] IE is not vulnerable to the attack by default. However, this can change depending on security zone settings.

Installation

The library can be installed via npm:

npm install --save blankshield

Or using bower:

bower install blankshield

Usage

blankshield.js works in global, CommonJS and AMD contexts.

blankshield(target)

blankshield is the main function exported by the library. It accepts an anchor element or array of elements, adding an event listener to each to help mitigate a potential reverse tabnabbing attack. For performance, any supplied object with a length attribute is assumed to be an array.

// It works on a single element
blankshield(document.getElementById('some-anchor'));

// Array-like objects such as HTMLCollections
blankshield(document.getElementsByClassName('user-submitted-link'));
blankshield(document.getElementsByTagName('a'));
blankshield(document.querySelectorAll('a[target=_blank]'));

// As well as jQuery
blankshield($('a[target=_blank]'));

// But make sure not to bind listeners to the anchors that would stop event
// propagation. In the example below, blankshield is not able to intercept the
// click behavior.
var anchor = document.getElementById('some-anchor')
anchor.addEventListener('click', function(e) {
   e.stopImmediatePropagation();
});
blankshield(document.getElementById('some-anchor'));

blankshield.open(strUrl, [strWindowName], [strWindowFeatures])

Accepts the same arguments as window.open. If the strWindowName is not equal to one of the safe targets (_top, _self or _parent), then it opens the destination url using "window.open" from an injected iframe, then removes the iframe. This behavior applies to all browsers except IE < 11, which use "window.open" followed by setting the child window's opener to null. If the strWindowName is set to some other value, the url is simply opened with window.open().

// To open an url with blankshield, instead of window.open()
blankshield.open('https://www.github.com/danielstjules');

// To bind a listener using jQuery with event delegation
// (Assumes no other listeners prevent propagation)
$('body').on('click', 'a[target=_blank]', function(event) {
  var href = $(this).attr('href');
  blankshield.open(href);
  event.preventDefault();
});

blankshield.patch()

Patches window.open() to use blankshield.open() for _blank targets.

blankshield.patch();

Solutions

A handful of solutions exist to prevent this sort of attack. You could:

  • Remove or disallow target="_blank" for any anchors pointing to a different origin.
  • Append rel="noreferrer" to any links with target="_blank". When done, window.opener will be null from the child window. It's well supported among webkit-based browsers, though you'll fall short with IE and Safari. And of course, it prevents sending the referrer in the request headers. You could fall off as an identifiable source of traffic for some friendly sites.
  • Append rel="noopener" to any links with target="_blank". When done, window.opener will be null from the child window. See caniuse for current browser support.
  • Listen for the click event and prevent the default browser behavior of opening a new tab. Then, call window.open() with the href and set the the child's opener to null. Unfortunately, this does not work for Safari. Safari's cross-origin security prevents the modification of window.opener of a child window if it lies on a different origin, yet still allows the child window to access window.opener.location.
  • Listen for the click event and prevent the default browser behavior of opening a new tab. Inject a hidden iframe that opens the new tab, then immediately remove the iframe. This is what blankshield does.

More Repositories

1

jsinspect

Detect copy-pasted and structurally similar code
JavaScript
3,558
star
2

Stringy

A PHP string manipulation library with multibyte support
PHP
2,461
star
3

buddy.js

Magic number detection for JavaScript
JavaScript
867
star
4

pjs

Pipeable javascript. Quickly filter, map, and reduce from the terminal
JavaScript
419
star
5

pho

BDD test framework for PHP
PHP
284
star
6

mocha.parallel

Run async mocha specs in parallel
JavaScript
197
star
7

wsc

WebSocket client for the terminal
JavaScript
167
star
8

redislock

Node distributed locking using redis
JavaScript
110
star
9

php-pretty-datetime

Generates human-readable strings for PHP DateTime objects
PHP
57
star
10

pattern-emitter

Node event emitters with support for regular expressions
JavaScript
55
star
11

ServerLogStats

A web app that uses javascript and HTML5's FileApi to generate graphs, charts and tables for apache/nginx server logs.
JavaScript
49
star
12

SliceableStringy

Python string slices in PHP
PHP
48
star
13

node-internal-pubsub

A publish/subscribe API similar to that in node_redis, minus the redis
JavaScript
47
star
14

toragent

HTTP(S) requests through Tor for Node
JavaScript
32
star
15

hoops

Nested property access and manipulation lib for node and browser
JavaScript
29
star
16

swaddle

Automagically create API clients/wrappers in JavaScript
JavaScript
23
star
17

async-class

Cleaner ES6 async class methods
JavaScript
22
star
18

defer-analytics

Easily defer loading and firing events for analytics.js
14
star
19

oops.js

JavaScript
5
star
20

filepaths

Get paths to all files in dirs/subdirs in node
JavaScript
4
star
21

battleship-puzzles

Design and implementation of a battleships solitaire puzzle generator and algorithms to solve instances
Python
4
star
22

openports

Find multiple open ports in node
JavaScript
2
star
23

inspect-ast

A better way to view a compact JS abstract syntax tree
JavaScript
2
star
24

freemail-cli

Filters or selects free and disposable email addresses
JavaScript
2
star
25

labtracker

Django app used to keep track of equipment information and use in a university lab setting
Python
2
star
26

sqlmagic

JavaScript
1
star
27

dirmap

Accepts a dir path and returns an object mapping file names to their full path
JavaScript
1
star