When a link opens a URL in a new tab with target="_blank"
, it is very simple for the opened page to change the location of the original page because the JavaScript variable window.opener is not null and thus "window.opener.location can be set by the opened page. This exposes the user to very simple phishing attacks.
Imagine a link posted on a comment of a popular web site (say: http://petssocialnetwork.io/) that opens a new tab that changes the URL of the original page to http://petssocialnetwork-pishing.io/. On "http://petssocialnetwork-pishing.io/" you land at a fake login page similar to the one at "http://petssocialnetwork.io/" but controlled by the hacker and asking the user to log in again, pretending that the session just timed-out.
To prevent pages from abusing window.opener, use rel=noopener
on <a href=>
to force its value to be null on the opened pages. With this in place, window.opener is null in Chrome 49+, Opera 36+, Firefox 52+, Desktop Safari 10.1+, and iOS Safari 10.3+. For older browsers, use "noreferrer"
. Cumulatively, rel="noopener noreferrer"
is the safest way to mitigate this vulnerability.
Noncompliant Code Example
<a href="http://dangerouswebsite.com" target="_blank"> <!-- Noncompliant; "window.opener" will be not null on the new tab/window and can be changed by http://dangerouswebsite.com -->
<a href="http://dangerouswebsite.com" target="_blank" rel="noopener"> <!-- Noncompliant; will not prevent the attack on old browsers -->
<a href="{{variable}}" target="_blank" rel="noopener"> <!-- Noncompliant -->
Compliant Solution
<a href="http://dangerouswebsite.com" target="_blank" rel="noopener noreferrer"> <!-- Compliant -->
Exceptions
No Issue will be raised when href contains a hardcoded relative url as there it has less chances of being vulnerable. An url is considered hardcoded and relative if it doesn't start with http:// or https://, and if it does not contain any of the characters {}$()[]
<a href="internal.html" target="_blank" > <!-- Compliant -->
See
Top comments (1)
Nice Ngan. +1 as today I leaned something from your post. Second, I will request to always apply server side security measures. CSRF token with some age.