target=”_blank”のタブナビング攻撃とは?対策・SEO影響・WordPress/ブラウザ最新事情

target blank”の危険性と対策 Security
この記事は約11分で読めます。

この記事は、以下の3記事の内容と、公開されているWeb情報(MDN / WordPress Trac / caniuse / OWASP など)を踏まえて、「いま結局どうすればいいの?」 に迷わないようまとめたものです。

  1. target=”_blank” とは
  2. タブナビング攻撃(Reverse Tabnabbing)とは
  3. なぜ起きる? window.opener の仕組み
  4. 対策の基本:rel=”noopener” と rel=”noreferrer”
    1. rel=”noopener”(元タブへの参照を切る)
    2. rel=”noreferrer”(参照元情報も渡さない)
  5. 実務で迷わないための書き方パターン
    1. パターン1:外部リンクを別タブで開く(参照元は渡してOK)
    2. パターン2:外部リンクを別タブで開く(参照元を渡したくない)
    3. パターン3:そもそも別タブで開かない(迷ったらこれ)
  6. SEO・計測・パフォーマンスへの影響
    1. SEO(検索ランキング)への影響
    2. アクセス解析・アフィリエイト計測への影響
    3. パフォーマンスへの影響
  7. 最新ブラウザ事情:暗黙の noopener が標準化
    1. それでも rel=”noopener” を書くべき理由
    2. 逆に opener を使いたいケース
  8. WordPress の対応状況
    1. WordPress は target=”_blank” に rel を自動付与してきた
    2. WordPress 5.6 で noreferrer がデフォルトから外れた
    3. WordPress 6.5 以降:”noopener も不要では?” という議論
  9. 自サイトの target=”_blank” をチェックする方法
    1. 手動で確認する場合
    2. サイト全体をクローリングする場合
  10. 既存記事を一括修正する方法(WordPress向け)
    1. 方法A:保存時に自動補正する
    2. 方法B:投稿コンテンツを一括修正する
  11. チェックリスト
  12. よくある質問
    1. Q. 「いまはブラウザが暗黙 noopener だから、もう何もしなくてOK?」
    2. Q. rel=”noopener noreferrer” と rel=”noreferrer” はどちらが正解?
    3. Q. 内部リンクも別タブで開くべき?

target=”_blank” とは

target="_blank" は、リンク先を新しいタブ(またはウィンドウ)で開くための指定です。

<a href="https://example.com" target="_blank">別タブで開く</a>

UI的には便利で、たとえば次のような場面で使われます。

  • 外部サイト(規約、地図、決済画面など)を参照しながら、元ページでの入力を続けてほしいとき
  • 管理画面やダッシュボードから、別サイトを確認する導線として

ただし、この便利さにはセキュリティ上の落とし穴があります。それが本記事のテーマです。

タブナビング攻撃(Reverse Tabnabbing)とは

タブナビング(Reverse Tabnabbing)とは、次のような流れで成立する攻撃です。

  1. あなたのサイト A に target="_blank" のリンクがある
  2. ユーザーがクリックし、外部サイト B が新しいタブで開く
  3. サイト B 側の JavaScript が、元タブ(サイト A)を勝手に別ページへ遷移させる
  4. ユーザーが元タブに戻ると、“いつものログイン画面に見せかけた偽ページ” が表示されている
  5. ユーザーが気づかずに情報を入力してしまう

ポイントは「ユーザーが元タブに戻ることを前提にしている」点です。人間の認知バイアスを突くフィッシング手法であり、注意していても引っかかりやすい厄介な攻撃といえます。

なぜ起きる? window.opener の仕組み

この攻撃が成立する原因は、window.opener というブラウザの仕組みにあります。

target="_blank" で新しいタブを開くと、リンク先(子タブ)から元タブへアクセスするための参照が自動的に渡されます。これが window.opener です。

  • 元タブ(あなたのサイト)から子タブ(リンク先サイト)を開く
  • 子タブ側の JavaScript から window.opener 経由で元タブを操作できる
  • その結果、元タブの URL を書き換えられてしまう

悪意あるコードのイメージはこうなります。

// 子タブ(リンク先)で動く悪意あるコードの例
if (window.opener) {
  window.opener.location = "https://phishing.example/login";
}

たったこれだけで、元タブがフィッシングサイトに書き換わります。

対策の基本:rel=”noopener” と rel=”noreferrer”

対策はシンプルで、子タブから元タブへの参照を切ることです。

rel=”noopener”(元タブへの参照を切る)

<a href="https://example.com" target="_blank" rel="noopener">安全に別タブ</a>

noopener を指定すると、window.openernull になります。子タブから元タブを操作できなくなるため、タブナビング対策の本命です。

rel=”noreferrer”(参照元情報も渡さない)

<a href="https://example.com" target="_blank" rel="noreferrer">さらに強い対策</a>

noreferrer は、HTTP の Referer ヘッダー(参照元 URL)を送信しません。加えて、仕様上 noopener と同等の挙動も含まれます

つまり、セキュリティ面だけを考えるなら noreferrer 単独でも noopener 相当の効果があるということです。ただし実務では、意図を明示するために rel="noopener noreferrer" と両方書く慣習も根強く残っています。

実務で迷わないための書き方パターン

結論として、次の3パターンを覚えておけば迷いません。

パターン1:外部リンクを別タブで開く(参照元は渡してOK)

<a href="https://example.com" target="_blank" rel="noopener">外部サイト</a>

もっとも一般的な形です。アクセス解析やアフィリエイト計測で参照元が必要な場合はこちら。

パターン2:外部リンクを別タブで開く(参照元を渡したくない)

<a href="https://example.com" target="_blank" rel="noopener noreferrer">外部サイト</a>

参照元 URL にクエリパラメータや個人情報が含まれる可能性がある場合、あるいは管理画面・社内ツールなど参照元を漏らしたくない場面で使います。

パターン3:そもそも別タブで開かない(迷ったらこれ)

<a href="https://example.com">外部サイト</a>

「別タブにしたい理由」を明確に説明できないなら、基本は同一タブ遷移で十分です。モバイルでは”タブの増殖”がユーザー体験を悪化させることも多いため、安易な別タブ指定は避けましょう。

SEO・計測・パフォーマンスへの影響

この観点での検索需要が多いので、丁寧に整理します。

SEO(検索ランキング)への影響

rel="noopener"rel="noreferrer" 自体が検索ランキングを上下させることはありません。「これを付けたらリンク評価が落ちる」といった話ではないので、安心してください。

ただし、間接的に影響しうるのは次に述べる「計測」の部分です。

アクセス解析・アフィリエイト計測への影響

rel="noreferrer" は参照元を送信しなくなるため、以下の影響が出ます。

  • GA4 などで参照元が取得できない(”direct” 扱いが増える)
  • アフィリエイトや紹介プログラムでリファラ依存の計測ができなくなる

運用上の痛みが出やすいポイントです。そのため、

  • 計測が重要な外部リンクnoopener のみ
  • 参照元を渡したくない外部リンクnoopener noreferrer

というように、用途に応じて使い分けるのが現実的です。

パフォーマンスへの影響

window.opener が存在すると、ブラウザの実装によってはプロセス分離がしにくくなり、パフォーマンス上の足かせになることがあります。

noopener を付けることで、ブラウザが最適化しやすくなり、間接的なメリットが得られるケースがあります。ただし、体感できるほど劇的な差が出るわけではなく、安全対策のついでに得られる副次的なメリットという位置づけで捉えてください。

最新ブラウザ事情:暗黙の noopener が標準化

2020年代後半のアップデートとして押さえておきたい点があります。

現在の主要ブラウザでは、target="_blank" を指定するだけで、暗黙的に noopener 相当の挙動になる方向に進んでいます。

  • MDN でも「target="_blank"rel="noopener" と同等の挙動になる」と明記
  • caniuse の対応表でも、Chrome / Firefox / Safari など主要ブラウザは対応済み

つまり、以前ほど「必ず書かないと危険」という状況ではなくなってきたのは事実です。

それでも rel=”noopener” を書くべき理由

仕様上は不要になりつつあるものの、実務では明示しておくのが無難というのが多くの現場での結論です。理由は3つあります。

  1. 古いブラウザや組み込み WebView を完全に切れるとは限らない
  2. CMS やテンプレートが自動付与しているなら、あえて消す理由がない
  3. 「セキュリティを意識している」意図が HTML だけで伝わり、コードレビューしやすい

逆に opener を使いたいケース

稀ですが、あえて window.opener を使いたいケースも存在します。

  • OAuth / SSO のポップアップログイン
  • 決済ポップアップで「完了したら元画面に戻す」処理

この場合、ブラウザの暗黙 noopener が邪魔になるため、rel="opener" を明示して opener を許可する必要があります。用途はかなり限定的です。

WordPress の対応状況

WordPress を使っている方にとっては、ここが一番気になるところでしょう。

WordPress は target=”_blank” に rel を自動付与してきた

WordPress は以前から、投稿本文内のリンクで「新しいタブで開く」を指定すると、rel 属性を自動付与して安全側に倒す仕組みを持っていました。

WordPress 5.6 で noreferrer がデフォルトから外れた

WordPress 5.6 では、wp_targeted_link_rel() の挙動が見直され、デフォルトの noreferrer が削除されました。

背景には、次のような判断があります。

  • noreferrer は計測や参照元分析に影響が出る
  • 必要かどうかはサイト運営者が選べばよい

なお、過渡期には Gutenberg 側が noreferrer を出力し続けるなど、挙動の揺れもありました。

WordPress 6.5 以降:”noopener も不要では?” という議論

主要ブラウザが暗黙 noopener に対応してきたことで、WordPress 側でも以下のような議論が出ています。

  • 管理画面の静的リンクから noopener を外す
  • 将来的に wp_targeted_link_rel() をどうするか

ただし、投稿本文(ユーザーコンテンツ)まで一気に外すのはリスクがあるため、現実には「まだ残す」方向に落ち着きやすい状況です。

自サイトの target=”_blank” をチェックする方法

手動で確認する場合

  1. ページを表示し、右クリック → 「検証」で開発者ツールを開く
  2. Elements パネルで target="_blank" を検索
  3. 該当リンクに rel が付いているかチェック

サイト全体をクローリングする場合

リンク数が多いなら、以下のようなツールが便利です。

  • Screaming Frog(リンク属性もチェック可能)
  • Sitebulb

target="_blank" があるが rel がない」リンクを一覧で抽出できると、修正作業が効率化します。

既存記事を一括修正する方法(WordPress向け)

⚠️ 注意: いきなり本番で一括置換を行うのは危険です。必ずバックアップを取り、ステージング環境で検証してから実行してください。

方法A:保存時に自動補正する

WordPress には、target="_blank" リンクの rel 属性を制御するフィルターがあります。

functions.php で noopener を必ず付与する例:

add_filter('wp_targeted_link_rel', function ($rel) {
    $rels = preg_split('/\s+/', trim((string) $rel));
    $rels[] = 'noopener';
    $rels = array_unique(array_filter($rels));
    return implode(' ', $rels);
});

参照元を渡したくない場合は noreferrer も追加:

add_filter('wp_targeted_link_rel', function ($rel) {
    $rels = preg_split('/\s+/', trim((string) $rel));
    $rels[] = 'noopener';
    $rels[] = 'noreferrer';
    $rels = array_unique(array_filter($rels));
    return implode(' ', $rels);
});

方法B:投稿コンテンツを一括修正する

投稿数が多い場合や、テーマ・プラグインをまたいで HTML 自体を統一したい場合は、DOM パーサーを使って安全に書き換えるのが王道です。正規表現による置換は予期せぬ事故を招きやすいため、避けることをおすすめします。

実装手段としては、

  • WP-CLI + PHP スクリプトで post_content を DOM 変換して更新
  • 一括修正用の管理画面ツールを自作

などがあります。

チェックリスト

  • target="_blank" を使う理由を明確に説明できる(”なんとなく” ではない)
  • 外部リンクで target="_blank" を使う場合、原則 rel="noopener" を付けている
  • rel="noreferrer" は参照元を渡したくない場合のみ使っている
  • 管理画面や社内ツールなど、参照元に情報が含まれうる場面では noopener noreferrer にしている
  • GA4 やアフィリエイト計測で noreferrer の影響を把握している
  • 既存コンテンツの一括修正は、バックアップ&ステージングで検証済み

よくある質問

Q. 「いまはブラウザが暗黙 noopener だから、もう何もしなくてOK?」

概ね安全にはなってきましたが、プロダクト品質を考えると以下の現実があります。

  • サポート対象ブラウザの範囲
  • 組み込み WebView の混在
  • CMS やテンプレートの自動出力

こうした点を踏まえると、rel="noopener" を明示する運用はまだ有効です。WordPress が自動で入れてくれるなら、そのまま活かすのが楽でしょう。

Q. rel=”noopener noreferrer” と rel=”noreferrer” はどちらが正解?

目的が「参照元を渡さない」なら、noreferrer 単独でも noopener 相当の挙動が含まれるため、理屈上は OK です。

ただし、チーム開発では意図が伝わりやすいように両方書くケースも多いです。どちらでも問題はありませんが、プロジェクトで統一しておくとよいでしょう。

Q. 内部リンクも別タブで開くべき?

基本的にはおすすめしません。 ユーザーの閲覧履歴や「戻る」操作を複雑にしやすく、モバイルでは特に「タブが増えるだけ」になりがちです。

別タブで開く明確な理由がない限り、内部リンクは同一タブ遷移で十分です。

コメント

タイトルとURLをコピーしました