为什么要使用“noopener”?小心安全漏洞。

2025-06-08

为什么要使用“noopener”?小心安全漏洞。

替代文本

TLDR:
查看此处的实现示例:
现场演示

让我们在网站内的新标签页中打开一个 URL

HTML方式


<a href="https://malicious-domain.netlify.com" target="_blank">Visit Malicious Website!</a>
Enter fullscreen mode Exit fullscreen mode

好的,这里我们有一个href恶意网站的属性,并且target作为_blank属性使其在新选项卡中打开。

假设用户点击了上述代码中的“访问恶意网站!”。他将被重定向到新标签页中的恶意网站。

流程看起来如此简单,用户在这里可能面临什么安全风险?

  • 用户从您的页面重定向到一个域。
  • 这时浏览器会把window你当前网站的变量内容全部附加到window.opener恶意网站的变量上。
    • 这是由拥有最大用户群之一的 Chrome 和 Firefox 浏览器实现的。
    • 因此现在恶意网站可以访问您的网站窗口,这显然在该方法的重定向中打开了一个安全漏洞。
    • 现在,恶意网站一旦通过它访问您的网站window变量,window.opener就可以将您之前的网站重定向到新的网络钓鱼网站,该网站可能看起来与您打开的实际网站类似,甚至可能要求您再次登录。
    • 只需编写以下代码即可在恶意网站中完成上述更改
  if (window.opener) {
    window.opener.location = 'https://www.dhilipkmr.dev';
  }
Enter fullscreen mode Exit fullscreen mode
  • 因此,无辜的用户会陷入这个陷阱,并提供可能暴露给攻击者的登录详细信息。

我们如何避免这种情况?

一个简单的方法是向标签添加一个rel属性noopener<a>

<a href="https://malicious-domain.netlify.com" rel="noopener" target="_blank">Visit Malicious Website!</a>
Enter fullscreen mode Exit fullscreen mode

它起什么作用?

  • rel="noopener"指示浏览器不要将当前网站的window变量附加到新打开的恶意网站上。
  • 这使得window.opener恶意网站的具有null其价值。

因此,当您将用户引导至非您维护的新域时,请务必小心。

我们并不总是使用标签打开新标签,a有时您必须通过执行window.open()如下所示的 JavaScript 来打开它,


function openInNewTab() {
  // Some code
  window.open('https://malicious-domain.netlify.com');
}
Enter fullscreen mode Exit fullscreen mode
<span class="link" onclick="openInNewTab()">Visit Malicious Website!</span>
Enter fullscreen mode Exit fullscreen mode

这里没有提到,noopener因此这会导致将window当前网站传递给恶意网站。

JavaScript 方式!

通过js打开新标签页时如何处理这种情况?

 function openInNewTabWithoutOpener() {
   var newTab = window.open();
   newTab.opener = null;
   newTab.location='https://malicious-domain.netlify.com';
 }
Enter fullscreen mode Exit fullscreen mode
<span class="link" onclick="openInNewTabWithoutOpener()">Visit Malicious Website!</span>
Enter fullscreen mode Exit fullscreen mode

这里,

  • 我们打开了一个虚拟标签页,通过window.open()它可以打开about:blank,这意味着它还没有重定向到恶意网站。
  • 然后我们修改opener新标签页的值如下null
  • 发布我们将新标签的url修改为恶意网站的url。
  • 这一次,再次opener将为空,因此无法访问window第一个网站的变量。

问题解决了。

但这种方法在旧版本的 Safari 中无法实现,所以我们再次遇到问题。

如何解决 Safari 的问题?

function openInNewTabWithNoopener() {
  const aTag = document.createElement('a');
  aTag.rel = 'noopener';
  aTag.target = "_blank";
  aTag.href = 'https://malicious-domain.netlify.com';
  aTag.click();
}
Enter fullscreen mode Exit fullscreen mode
<span class="link" onclick="openInNewTabWithNoopener()">Visit Malicious Website!</span>
Enter fullscreen mode Exit fullscreen mode

这里我们模拟点击锚标签。

  • 我们创建<a>标签并分配所需的属性,然后click()在其上执行,其行为与单击链接相同。
  • 不要忘记rel在这里给标签添加属性。

其他事实:

  • 当你点击CMD + LINK锚标签时,chrome、firefox 和 Safari 会将window.opener恶意网站视为null
  • 但是,在CMD + LINK通过 javascript 处理新标签打开的元素上,浏览器会附加window变量并将其发送到新标签。
  • 默认情况下,新版 Safariwindow.opener在所有情况下都会删除与锚标记一起使用的信息,要将window信息传递到新选项卡,您必须明确指定rel='opener'

在此处查看实时实现示例:
实时演示

无人能绕过您的安全。

关注我可能是 :P

我的网站博客Twitter

就这些了,伙计们!!!

鏂囩珷鏉ユ簮锛�https://dev.to/dhilipkmr/why-should-you-use-noopener-beware-of-security-flaws-3i57
PREV
JavaScript 学习路线图🚀
NEXT
了解如何记忆 JavaScript 函数