外部リンクtarget="_blank"の危険性 - Tabnabbing


はじめに

今回は、aタグにtarget="_blank"を指定することのリスクと対処法についてまとめます。


こういうやつ↓の危険性ですね。

<a href="hoge.html" target="_blank"></a>


target="_blank"の危険性


target="_blank"は、リンク先のページを新しいウィンドウで開く指定をする属性ですが、リンク先として開かれたウィンドウは同じプロセスとして動作します。なので、window.openerを用いてリンク先のページからリンク元のオブジェクトを操作することが可能です。

では、実際にwindow.openerを使ってリンク先のページからリンク元のオブジェクトをいじってみます。今回はリンク元ページのURLを当ブログURLに変更してみます。

parent.html(リンク元)

<html>
<head></head>
<body>
  <div style="text-align: center; margin-top: 100px;">
    <h1>親ページ</h1>
    <a href="./child.html" target="_blank" rel="noopener">新しいタブで開く</a>
  </div>
</body>
</html>


child.html(リンク先)

<html>
<head></head>
<body>
  <div style="text-align: center; margin-top: 100px;">
    <h1>子ページ</h1>
  </div>
</body>
<script>
  window.opener.location = "https://morelia.tokyo";
</script>
</html>


用意したparent.htmlをブラウザで開いてリンクをしてみると、↓のようにリンク元URLが変わってますね。


対策


<a>タグにrel="noopener"を指定します。

こうすることで、リンク先のwindow.openerの値がなくなり、リンク先ウィンドウとリンク元ウィンドウとの関係を断ち切ることによって操作不可にすることができます。

<a href="hoge.html" target="_blank" rel="noopener"></a>


ちなみに、WordPressで外部リンクを設置する場合はデフォルトでrel="noopener"が設定されるようです。

また、window.open()を使ってウィンドウを開く際も同様のことができてしまうので、window.openerの値を取り消します。

let newWindow = window.open();
newWindow.opener = null;


リンク先ページを開くと↓のエラーが出ており、操作失敗が確認できます。

Uncaught TypeError: Cannot set property 'location' of null
    at child.html:9

Tabnabbing


このようにリンク元のページを書き換える手法をTabnabbing(タブナビング)といいます。

Tabnabbingはフィッシングの一種で、リンク元を何らかのWebアプリ/サイトのログイン画面(SNS, 銀行のサイトなど)にすげ替えてログイン情報などを盗むことなどに悪用されるようです。

Tabnabbingが施されたサイトを閲覧するユーザはTabnabbingを防ぐ方法はありません。

なので、サイト/アプリ運営者が今回のような悪意あるスクリプトを埋め込まれないようXSS対策にする、また別ウィンドウから操作されないよう今回紹介した対策を忘れず行うようにしましょう。

今回は以上です。