「自分のつもりで押したボタンが、実は裏の別ページのボタンだった」。それがクリックジャッキングです。仕組みと、確実な防ぎ方を解説します(攻撃手順は載せません)。
何が狙われるか
「1クリックで完了し、しかも価値のある操作」が標的です。
| 標的になりやすい操作 | なぜ狙われる |
|---|---|
| 送金・購入の確定 | ワンクリックで金銭が動く |
| 設定変更(公開範囲・連携許可) | 後で乗っ取りや情報取得につながる |
| OAuth/権限の「許可」ボタン | アカウント連携を勝手に承認させられる |
| SNSのフォロー・いいね・投稿 | 勝手な拡散・いいね稼ぎに悪用 |
なぜ成立するか(仕組み)
ブラウザは、別サイトを iframe で読み込んで重ねて表示できます。攻撃者はその iframe を**透明(不透明度0)**にし、利用者に見えるのは下に置いたニセUIだけ。利用者が「ニセのボタン」を押すと、真上に重なった本物のボタンが押されます。
CSRF と似ていますが、CSRF が「裏でリクエストを送る」のに対し、クリックジャッキングは本物の画面を本人に操作させるため、ワンタイムトークン等のCSRF対策だけでは防げません。
具体例:ブラウザのプラグインの許可画面が狙われた(2008年)
2008年10月、Adobeはセキュリティアドバイザリ(APSA08-08)で、複数のブラウザに関わるクリックジャッキングの問題を公表しました。報道によれば、Flash Player の設定画面を透明に重ねることで、利用者が気づかないうちにWebサイトへカメラとマイクの利用を許可させられるおそれがありました。Adobeは修正版の Flash Player を公開し、それまでの回避策として、設定マネージャーで常に拒否する設定を案内しました。
この事例から分かるのは、狙われるのが送金ボタンだけではないことです。「許可」「同意」「連携する」のように、1回押すだけで権限が渡る画面はすべて対象になります。こうした弱点は、MITREの弱点分類では CWE-1021(描画されたUIのレイヤーやフレームの制限が不適切)に分類されています。
防御:他サイトへの埋め込みを禁止する
CSP frame-ancestors を設定(最優先)
レスポンスヘッダに Content-Security-Policy: frame-ancestors 'self'(自サイトのみ枠化を許可)。第三者に埋め込ませる必要がなければ 'none' が最も安全。許可する相手がいる場合だけドメインを列挙。
X-Frame-Options も併用(後方互換)
古い環境向けに X-Frame-Options: DENY(または SAMEORIGIN)も付ける。新旧ブラウザ両対応の多層防御。
重要な操作には、確認の手順を追加する
送金・権限付与など致命的な操作は、再認証・確認ダイアログ・直前の意図確認を挟む。透明な重ねでは突破しづらくなる。
セッションCookieを SameSite に
SameSite=Lax/Strict で、別サイト起点の自動送信を抑える。クリックジャッキング単体には万能ではないが、関連する“別サイト起点の操作”全般を弱められる。
X-Frame-Options と CSP frame-ancestors の違い
どちらも「他サイトに埋め込ませない」ためのヘッダですが、細かい点が違います。
| X-Frame-Options | CSP frame-ancestors | |
|---|---|---|
| 指定できる値 | DENY(すべて拒否)/SAMEORIGIN(同じオリジンだけ許可) | 'none'/'self'/許可するドメインの列挙 |
| 許可先を複数指定 | できない(ALLOW-FROM は今のブラウザで使えない) | できる |
| metaタグでの設定 | 効かない | 効かない |
| 両方あるとき | 対応ブラウザでは無視される | こちらが優先される |
| 役割 | 古いブラウザ向けの保険 | 今の主な対策 |
両方を送るときは、意味をそろえます。frame-ancestors 'none' には DENY、frame-ancestors 'self' には SAMEORIGIN を組み合わせます。
よくある設定ミス
- CSPの
default-srcだけで守れていると思っている:frame-ancestorsはdefault-srcの設定を引き継ぎません。default-src 'none'でも、frame-ancestorsを書かなければ埋め込みは許可されたままです - metaタグに書いている:HTMLの
<meta http-equiv>では効かないので、レスポンスヘッダで送ります Content-Security-Policy-Report-Onlyのまま:違反を報告するだけで、埋め込みは止めません。動作を確認したら本番のヘッダに切り替えます- 一部のページにしか付いていない:トップページだけ確認して、ログイン画面・設定画面・エラーページで抜けていることがあります。CDNやプロキシの設定でヘッダが外れていないかも確認します
自分のサイトで確認する方法
ヘッダ診断ツールで確認する
セキュリティヘッダ診断に自分のサイトのURLを入れ、X-Frame-Options と CSP の frame-ancestors が返っているかを見ます。トップページだけでなく、ログイン後の設定画面や、送金・権限付与のページのURLも確認します。
ブラウザの開発者ツールで確認する
開発者ツールの「ネットワーク」タブでページを再読み込みし、HTMLのレスポンスヘッダを開きます。ヘッダが2回重複して送られていたり、値が食い違っていたりしないかも見ます。
設定を一か所にまとめる
Webサーバー(nginx・Caddy)、リバースプロキシ、フレームワークのどれか一か所で全レスポンスに付けると、抜けと重複を防げます。CSPを新しく作るならCSPビルダーで frame-ancestors を含めて組み立てられます。
当サイトの視点:ヘッダ1行の設定が最も効果的。まず自分のサイトを確認する
クリックジャッキング対策は複雑なコードではなく、レスポンスヘッダ1〜2行で埋め込みを禁止するのが最短です。フレームワークやリバースプロキシ(Caddy/nginx)で全ページに一括付与し、抜け漏れを無くすのが実戦的。「設定したつもり」で抜けているのが一番多い事故なので、設定したら上の手順で実際に返っているかを確かめてください。
出典(一次情報)
- OWASP「Clickjacking Defense Cheat Sheet」 — cheatsheetseries.owasp.org(frame-ancestors・X-Frame-Options・SameSite、ALLOW-FROMが使えないこと、metaタグでは効かないこと、frame bustingの限界)
- MDN「CSP: frame-ancestors」 — developer.mozilla.org(指定できる値、default-srcを引き継がないこと、metaタグ非対応)
- RFC 7034「HTTP Header Field X-Frame-Options」 — rfc-editor.org
- IPA「安全なウェブサイトの作り方 1.9 クリックジャッキング」 — ipa.go.jp
- Adobe「Security Advisory for Flash Player (APSA08-08)」(2008年10月7日) — adobe.com
- Computerworld「Clickjackers could hijack webcams, microphones, Adobe warns」(2008年10月) — computerworld.com(カメラとマイクの許可画面が狙われたこと)
- MITRE「CWE-1021: Improper Restriction of Rendered UI Layers or Frames」 — cwe.mitre.org
次に読む
- 用語:CSRF とは / XSS とは
- 解説:セキュリティヘッダの選び方(今も必要なもの・不要になったもの)
- 確認:セキュリティヘッダ診断 / CSPビルダー