サイドチャネル攻撃の悪夢を断つ:COOPとCOEPでブラウザを「密室」にする技術
「ブラウザのタブが別々なら、Webサイト間のデータは漏れない」。かつてはこの前提が安全の基礎でした。しかし、SpectreのようなCPUの投機的実行に起因する脆弱性が発覚して以来、その前提は崩壊しました。
攻撃者は、同じブラウザプロセス内で実行されている別のタブのメモリ領域を、JavaScriptのわずかなタイミング差(サイドチャネル)を利用して読み取ることが可能です。これを防ぐために登場したのが、COOP (Cross-Origin Opener Policy) と COEP (Cross-Origin Embedder Policy) です。
今日は、教科書的な説明は飛ばして、現場でこの二つをどう実装し、なぜ「今の時代、これがデフォルトであるべきか」を深掘りします。
—
なぜ「分離」が最強の防壁なのか
想像してください。あなたのWebアプリが、ユーザーの機密情報(セッション情報や個人データ)を表示しているとします。通常、攻撃者はそのページに直接アクセスできません。しかし、攻撃者が用意した悪意あるページにユーザーを誘導し、window.open等であなたのサイトを開かせると、ブラウザのプロセス共有という「緩い境界」が仇となり、メモリ上のデータがスキャンされるリスクが生じます。
これを防ぐのが「オリジンによる隔離(Isolation)」です。
1. COOP (Cross-Origin Opener Policy)
「俺のタブに、他のサイトから干渉させない」。これを強制します。same-originを設定すると、別サイトからのリンク(ポップアップ等)であっても、ウィンドウの参照関係を完全に切り離し、攻撃者からのクロスオリジン操作をシャットアウトします。
2. COEP (Cross-Origin Embedder Policy)
「俺のページに埋め込まれるなら、お前も安全な許可を得てこい」。これを強制します。たとえ自サイト内のリソースであっても、明示的な許可(CORS設定)がないものはロードを拒否します。これにより、攻撃者が外部リソースを介してサイドチャネル攻撃を行う隙を埋めます。
—
実務で直面する「画面が真っ白」問題
COOP/COEPをいきなり本番環境に入れると、高確率で画面が真っ白になります。サードパーティの広告スクリプトや、埋め込み画像、CDN上のライブラリが「許可がない」とみなされ、ブラウザにブロックされるからです。
「とりあえず導入」は厳禁です。 以下の手順で進めてください。
Nginxでの実装例(まずはReport-Onlyで監視)
いきなりブロックするのではなく、まずは Report-Only ヘッダーを使って、どのリソースが弾かれるかログを収集します。
Nginx設定ファイル例
server {
# 完全に遮断する前に、まずはレポートモードで違反を検知する
add_header Cross-Origin-Opener-Policy-Report-Only “same-origin”;
add_header Cross-Origin-Embedder-Policy-Report-Only “require-corp”;
# レポート送信先を指定(ブラウザがここにJSONを投げてくれる)
add_header Report-To ‘{“group”:”csp-endpoint”,”max_age”:10886400,”endpoints”:[{“url”:”https://your-domain.com/csp-report”}]}’;
}
—
完全に防御するためのセキュアな実装コード
調査が完了し、必要なリソース(CORS対応済みの外部スクリプト等)が確定したら、本番用のヘッダーを適用します。
PHPアプリケーションでの強制設定
なぜこれが必要なのか:エンジニアの心得
「うちのサイトは大した情報を扱っていないから関係ない」という慢心が、最も危険です。攻撃者は、あなたのサイトを「踏み台」として利用します。あなたのサイトが攻撃者の標的となり、ログイン中のユーザーのブラウザを乗っ取って、別の金融サイトへ攻撃を仕掛ける……といった連鎖インシデントを防ぐ責任が、開発者にはあります。
COOP/COEPを導入するということは、単に「セキュリティヘッダーを付ける」という作業ではなく、「ブラウザのメモリ空間を独占し、攻撃者の介入を許さない」というアーキテクチャ上の意思表示なのです。
—
まとめ:現場で意識すべきチェックリスト
1. 段階的導入: まずは Report-Only モードで数週間運用し、Consoleのエラーログを徹底的に洗う。
2. CORSの再確認: 外部リソース(APIやCDN)には Access-Control-Allow-Origin と Cross-Origin-Resource-Policy: cross-origin が適切に設定されているか。
3. SharedArrayBufferの恩恵: このヘッダー設定を行うことで、パフォーマンス最適化のための SharedArrayBuffer や performance.now() の高精度タイマーが利用可能になります。セキュリティ向上とパフォーマンス向上が両立できる数少ない設定です。
「脆弱性が出たら直す」という受動的な姿勢から、「ブラウザの仕様を味方につけて、攻撃の芽を摘む」という能動的な姿勢へ。このヘッダー設定は、そのための第一歩です。今日から、君のWebアプリを「密室」にアップデートしてください。
コメント