target="_blank"のリンクを踏んだのにwindow.openerにnullが入ることについて
目次
- 目次
- target="_blank"の危険な理由
- “target=_blank”のリンクは“rel=noopener”が付いているものとして扱われることになった
- window.open関数を使えばwindow.openerにはアクセスできる
- target="_blank"の危険な動作を試す
target="_blank"の危険な理由
最近、aタグについて調べる機会があった。
<a href="http://example.com" target="_blank">insecure link</a>
というリンクを作成した際に、リンク元でopenerの情報にアクセスできてしまうという話は普段web系の分野で動かれている方にとっては有名な話だが、では、試しにその手法を試してみようと思って簡単なサンプルを作成した際に、window.opener
の中が null
になっていることに気づいた。
※本来上に貼ったinsecure link
を踏んだ場合、window.opener
に遷移元のページ情報が格納されており、この情報を悪用して遷移先のページで下記のようなJavaScriptを埋め込んでおくことで指定したページに遷移させることが可能になるというものだったかと思う。
window.opener.location = 'http://example.com';
ただし、上にも書いたように window.opener
の中身は null
になっていた。
“target=_blank”のリンクは“rel=noopener”が付いているものとして扱われることになった
これについては下記のような変更が行われたようだ。
確かにセキュリティ面を考えると、こちらのほうが安全ではある。
window.open関数を使えばwindow.openerにはアクセスできる
ではもうwindow.openerにはnullしか入らなくなったのだろうか、というとそんなことはなく、window.open
関数を使って遷移を行った場合には注意が必要だ。
例えば下記のようなリンクがある場合、window.opener
には情報が入る。
<a href="./index2.html" target='_blank' onclick="window.open(this.href,this.target);return false;">insecure link</a>
onclickイベントの最後に "return false;"を付ける理由
ちなみに少し話がそれるが、上のコードでonclick
イベントでの処理の最後に return false;
を書いているのはリンクの既定のアクションをキャンセルすることが目的となるらしい。
ここについてはMDNの下記のページが詳しい。
https://developer.mozilla.org/ja/docs/Web/API/Window/open#best_practices
コード内の return false の目的は、リンクの既定のアクションをキャンセルすることです。 onclick イベントハンドラーが実行される場合、リンクの既定のアクションを実行する必要はありません。しかし、ユーザーのブラウザー で javascript サポートが無効、もしくは、存在しない場合、onclick イベントハンドラーは無視され、ブラウーーは、target の "PromoteFirefoxWindowName" という名前のフレーム、もしくは、ウィンドウ内の参照されたリソースを読みこみます。
しかし、いまいち、return false:
を書いたときにどう動作が変わってくるのかがまだ理解できていない。
これについては別途時間を見つけて調べて見るかもしれない。
window.openerに情報が入るパターンのリンクについて
window.openerに値が入るリンクを上に書いたが、他にもパターンはあるので、ここではそれを列挙してみようと思う。
まずは上に書いたパターンで、onclickでwindow.openを利用したパターンだ。
ちなみにwindow.open
関数は第2引数にaタグでいうtarget属性となる、windowNameが指定できる。
<a href="./index2.html" target='_blank' onclick="window.open(this.href,this.target);return false;">insecure link</a>
次にwindow.open(url)
というパターン。
<a href="./index2.html" onclick="window.open(this.href);return false;">insecure link 2</a>
第2引数に_blank
を指定したわけではないのに、遷移後のページでwindow.opener
の中に情報が入っている。
次はrel="noopener noreferrer"
を指定してもwindow.open関数では特にそれらを指定していない場合。
<a href="./index2.html" target='_blank' rel="noopener noreferrer" onclick="window.open(this.href,this.target);return false;">insecure link 3</a>
ちなみに、return false;
の記述を削除しても、この挙動は変わらなかった。
<a href="./index2.html" target='_blank' rel="noopener noreferrer" onclick="window.open(this.href,this.target)">insecure link 3</a>
window.openを使った遷移してもwindow.openerに何も入れないためにはどうすればよいか?
これは上に貼ったMDNのページ内にも書いてあるが、下記のように第3引数に"noopener noreferrer"
を記述すれば window.opener
はnullとなる。
<a href="./index2.html" target='_blank' onclick="window.open(this.href,this.target, 'noopener noreferrer');return false;">secure link2</a>
というわけで、window.openerについて調べてみた備忘録でした。
target="_blank"の危険な動作を試す
なお、これらのコードはGitHubにあげています。
人のサーバで危険な動作を試すのは抵抗あると思うので(私は怖い)、GitHubからダウンロードしてローカルでお試しください。
実際の動作としては insecure link
を踏むと、踏んだ遷移先のページで下記のようなJavaScriptが動く。
console.log(window.opener); if(window.opener) { window.opener.location = "./index3.html"; }
遷移元のページがリンクをクリックした直後に意図しないページに変わっているのが確認できる。