target="_blank" 安全问题

使用 target="_blank" 的安全隐患及解决方案

问题

target="_blank" 有哪些问题?如何解决?

解答

安全问题:window.opener 漏洞

当使用 target="_blank" 打开新页面时,新页面可以通过 window.opener 访问原页面的 window 对象。

<!-- 原页面 A -->
<a href="https://malicious-site.com" target="_blank">点击访问</a>
// 恶意页面 B 可以执行以下代码
if (window.opener) {
  // 将原页面重定向到钓鱼网站
  window.opener.location = 'https://fake-login.com';
}

这种攻击被称为 Tabnabbing:用户点击链接后,原页面被悄悄替换成钓鱼页面,用户切回时可能输入敏感信息。

性能问题

新页面和原页面在某些浏览器中共享同一进程,新页面的高负载会影响原页面性能。

解决方案

方案一:添加 rel 属性

<!-- 推荐写法 -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">
  外部链接
</a>
  • noopener:新窗口的 window.openernull
  • noreferrer:不发送 Referer 请求头,同时包含 noopener 的效果

方案二:JavaScript 方式

function openWindow(url) {
  const newWindow = window.open(url, '_blank');
  // 手动清除 opener 引用
  if (newWindow) {
    newWindow.opener = null;
  }
}

方案三:使用 noopener 特性

// 通过 windowFeatures 参数指定 noopener
window.open('https://example.com', '_blank', 'noopener');

验证 opener 是否被阻止

<!-- 测试页面 -->
<!DOCTYPE html>
<html>
<head>
  <title>Opener 测试</title>
</head>
<body>
  <script>
    if (window.opener) {
      console.log('可以访问 opener:', window.opener);
    } else {
      console.log('opener 为 null,安全');
    }
  </script>
</body>
</html>

关键点

  • target="_blank" 会让新页面通过 window.opener 访问原页面
  • 攻击者可利用此漏洞将原页面重定向到钓鱼网站(Tabnabbing)
  • 使用 rel="noopener noreferrer" 是最简单的解决方案
  • 现代浏览器(Chrome 88+)已默认对跨域链接添加 noopener,但仍建议显式声明