关于 rel=noopener

英文原版

1. 它在解决什么问题

你当前正在查看 index.html

想象下以下是用户在你的网站上生成的内容:

<a class="user-generated" href="malicious.html" target="_blank">
    <b>Click me!!1 (同域)</b>
</a>

点击以上的链接打开 malicious.html 在一个新的标签页上(使用 target=_blank). 本身,这并不令人兴奋。

但是,malicious.html 文档在新的标签页有一个 window.opener 属性指向当前你正在看的HTML文档的 window 对象,例如这个: index.html

这意味着,如果用户点击了这个链接,malicaous.html 能够完全的控制当前文档的 window 对象。

请记住即使 index.htmlmalicaous.html 属于不同的域这也是有效的,window.opener.location 跨域情况下依然能获取到!(虽然 window.opener.document 在跨域的情况下获取不到,CORS也是无效的),以下是一个跨域的链接:

<a class="user-generated" href="https://mathiasbynens.be/demo/opener" target="_blank">
<b>Click me!!1 (跨域)</b>
</a>

malicious将当前页面 index.html 换成了 index.html#hax, 这使得当前页面展示了一个隐藏信息。这是个相对来说无害的例子,但是取而代之的可以是重定向到一个钓鱼网站,设计得就像真的 index.html 一样,要求你登录。用户不会注意到这些,因为注意力在新开的 malicaous 页面,然而重定向发生在后台。攻击可以通过在重定向到钓鱼网站之前增加延迟使得更为巧妙(查看).

如果 window.opener 被设置了,一个页面可以无视安全源触发 opener 页面的导航。

2. 推荐做法

为了避免页面滥用 window.opener 使用 rel=opener,在 Chrome 49 & Opear 36, Firefox 52, Desktop Safari 10.1+ 和 iOS Safari 10.3+中 它能够保证 window.openernull.

<a class="user-generated" href="malicious.html" target="_blank" rel="noopener">
<b>Click me!!1 (使用 rel=noopener)</b>
</a>

对于更老的浏览器,你可以设置 rel=noreferer, 这样也能禁用掉 Referer 的 HTTP 头, 或者以下的 JavaScript 代码可能会触发弹出式窗口的拦截器:

var otherWindow = window.open();
otherWindow.opener = null;
otherWindow.location = url;
<a class="user-generated" href="malicious.html" target="_blank" rel="noreferrer">
<b>Click me!!1 (now with <code>rel=noreferrer</code>-based workaround)</b>
</a>
<a class="user-generated" href="malicious.html" target="_blank" onclick="var otherWindow = window.open(); otherWindow.opener = null; otherWindow.location = href; return false;">
<b>Click me!!1 (now with <code>window.open()</code>-based workaround)</b>
</a>

记住 基于JavaScript的方式在Safari上无效,为了 Safari 的支持,插入一个隐藏的 iframe 去打开新的页面,然后立刻移除 iframe.

不要使用 target="_blank"(或者其他的 target 打开新的导航上下文),尤其是对于那些用户生成的链接内容,除非你有好的理由这样做。

3. 说明

Safari Technology Preview 68, 锚点上的 target="_blank" 意味这 rel="noopener", 如果明确的选择保留 window.opener,使用 rel="opener", 查看这里

4. Bug 追随清单

Last updated