クリックジャッキングの仕組みとフレーム制御による対策
対象の目安: Webアプリ開発者と運用担当 / 実務

クリックジャッキングは、利用者が画面で見ているボタンやリンクと、実際にクリックされる要素とがすり替えられている攻撃です。攻撃者は自分が用意したページの前面に、標的となる正規サイトを透明なiframeで重ね、その奥に無害そうなボタンを見せます。利用者は見えているボタンを押したつもりでも、実際にはその手前にある透明なiframe内の正規サイトの操作要素をクリックしており、送金や設定変更、権限付与といった意図しない操作が実行されます。UIリドレッシング(UI Redressing)とも呼ばれます。
この記事では、クリックジャッキングがどのような重ね合わせで成立するのか、何が実行され得るのか、そしてサーバー側のフレーム制御を中心にどう防ぐのかを、開発者向けに整理します。攻撃を再現する手順や実際に動くコードは示しません。動作確認を行う場合は、自組織が管理する検証環境に限って実施してください。
クリックジャッキングが成立する仕組み
攻撃者のページは、標的サイトのページを<iframe>で読み込み、CSSで不透明度をゼロ近くまで下げて透明化します。そのうえで、利用者に見せたいボタンやコンテンツを、透明なiframeの操作要素とちょうど重なる位置に配置します。透明化された標的サイトのiframeが最前面にあり、利用者の目にはその奥に置かれた見せかけのボタンだけが映る状態になります。
利用者が見えているボタンをクリックすると、透明なiframeが最前面にあるため、実際にクリックされるのは奥の見せかけの要素ではなく、前面の透明なiframe内にある標的サイトの本物の操作要素です。標的サイトは利用者が既にログイン済みであれば、そのセッションのまま操作を受け付けます。マウス位置に合わせて標的サイトを動かし、複数回のクリックを誘導する手法もあります。
この弱点はCWE-1021(Improper Restriction of Rendered UI Layers or Frames)として整理されています。派生には、SNSのいいねボタンを押させるLikejacking、カーソルの表示位置を実際の位置とずらして誤操作させるCursorjackingなどがあります。
CWE-1021は、Webアプリが他のアプリケーションやドメインに属するフレームやUIレイヤーを適切に制限しない弱点で、クリックジャッキングやUIリドレス攻撃とも呼ばれると定義しています。
何が実行され得るか
クリックジャッキングで盗まれるのは、多くの場合データそのものではなく操作です。ページ内のテキストを読み取るのではなく、利用者のセッションを使って利用者本人に代わって操作を実行させる点が特徴です。標的が扱う機能に応じて、次のような操作が悪用の対象になります。
| 標的機能の例 | 誘導され得る操作 |
|---|---|
| 送金、決済 | 送金の確定、支払いの承認 |
| アカウント設定 | メールアドレスや通知先の変更、二要素認証の無効化 |
| 権限管理 | 連携アプリへの権限付与、管理者権限の委譲 |
| SNS | 投稿の公開、フォロー、いいね |
| 退会、削除 | アカウント削除、データ消去の確定 |
いずれも利用者本人が正規サイト上で実行できる操作であり、クリックジャッキングはその実行タイミングと対象を攻撃者が誘導している状態です。したがって、標的サイト側が枠内表示そのものを制御できれば、この誘導は成立しなくなります。
主対策はCSPのframe-ancestors
現行の推奨対策は、Content-Security-Policyヘッダのframe-ancestorsディレクティブで、自サイトを枠内に表示できるオリジンを宣言的に制限することです。frame-ancestorsは<frame>、<iframe>、<object>、<embed>による埋め込みについて、直接の親だけでなく全ての祖先フレームのオリジンを検査し、一つでも許可リストに無ければ読み込みを拒否します。ネストしたフレーム構成では、全ての祖先オリジンを許可リストに含める必要があります。枠内表示を一切許可しない場合は次のように設定します。
Content-Security-Policy: frame-ancestors 'none';
自サイト自身からの埋め込みだけを許可する場合は'self'を、特定の信頼オリジンからの埋め込みを許可する場合はホストを列挙します。
Content-Security-Policy: frame-ancestors 'self' https://partner.example.com;
OWASPは、埋め込みの必要が特定できない限り枠内表示を許可しない設定を推奨しています。frame-ancestorsはdefault-srcにフォールバックしないため、default-src 'none'を設定していても埋め込み制御には別途frame-ancestorsの記述が必要です。なお、frame-ancestorsは<meta>要素では指定できず、HTTPレスポンスヘッダとして返す必要があります。
X-Frame-Optionsとの使い分け
X-Frame-Optionsは、frame-ancestorsが標準化される前から使われてきたヘッダで、DENYとSAMEORIGINの2つの値を実務では使います。DENYはあらゆるオリジンからの枠内表示を禁止し、SAMEORIGINは同一オリジンからの埋め込みのみを許可します。かつて存在したALLOW-FROMは非推奨で、モダンブラウザではサポートされていません。特定オリジンへの許可が必要な場合はframe-ancestorsで表現します。
X-Frame-Options: DENY
frame-ancestorsとX-Frame-Optionsを両方返した場合、frame-ancestorsに対応するブラウザはCSPのframe-ancestorsを優先し、X-Frame-Optionsを無視します。frame-ancestorsを主対策としつつ、それに未対応な古いブラウザ向けの後方互換としてX-Frame-Optionsを併記する、という重ね方が現実的です。ただしX-Frame-Optionsが実質的に表現できるのはDENYとSAMEORIGINだけで、ALLOW-FROMは廃止済みのため、第三者オリジンの許可をX-Frame-Optionsで同じ範囲に表現することはできません。両者を完全に整合させられるのは概ねframe-ancestors 'none'とDENY、'self'とSAMEORIGINの場合に限られ、第三者オリジンを許可する構成では、frame-ancestorsに未対応な古いブラウザで埋め込みが拒否されるなど後方互換の差が出ます。
ヘッダだけに頼らない多層防御
フレーム制御ヘッダは主対策ですが、それだけに頼らず操作側の保護を重ねます。送金や権限変更のような不可逆または影響の大きい操作には、実行直前の再認証や確認ステップを設けると、1回のクリックでは完了しなくなり、誘導の成立を妨げられます。なお、anti-CSRFトークンの検証はクリックジャッキングそのものを防ぐ緩和策にはなりません。枠内に読み込まれた正規ページ自身が有効なトークンを保持しており、そこから正規のリクエストが送られてしまうためです。CSRF対策はクロスサイトリクエストフォージェリという別の脅威に対する必須の対策として、クリックジャッキング対策とは切り分けて実装します。
CookieのSameSite属性をLaxまたはStrictにすると、クロスサイトのiframeからのリクエストにセッションCookieが付与されにくくなり、影響を緩和できます。一方、JavaScriptでフレーム内表示を検出して抜け出すフレームバスティングは、サンドボックス属性などで無効化され回避されやすく、単独の対策としては不十分です。フレームバスティングを使う場合でも、ヘッダによる制御を主とし、あくまで補助に留めます。
導入と検証の手順
- 1
自サイトのフレーム化可否を確認する
主要ページのHTTPレスポンスヘッダを確認し、Content-Security-Policyのframe-ancestorsとX-Frame-Optionsが返っているかを調べます。どちらも無ければ、任意のオリジンから枠内に埋め込める状態です。ログイン後の操作画面や重要操作のページを優先して確認します。
- 2
フレーム制御ヘッダを設定する
埋め込みの必要がなければ
Content-Security-Policy: frame-ancestors 'none';を全レスポンスに付与します。同一オリジンでの埋め込みが必要なら'self'、特定パートナーのみ許可するならオリジンを列挙します。後方互換としてX-Frame-Options: DENYまたはSAMEORIGINを許可範囲に合わせて併記します。 - 3
重要操作を保護する
送金、設定変更、権限付与、退会などの操作に、実行直前の確認ステップや再認証を追加し、1回のクリックでは完了しないようにします。CookieにはSameSite属性を設定します。CSRFトークン検証はクリックジャッキングを防ぐものではありませんが、クロスサイトリクエストフォージェリ対策として別途必須です。
- 4
設定を検証する
検証環境で対象ページのヘッダが期待どおり返るかを確認し、埋め込みを許可したオリジンからのみフレーム表示できることを確かめます。frame-ancestorsとX-Frame-Optionsの許可範囲を突き合わせ、第三者オリジンを許可する構成ではX-Frame-Optionsで同じ範囲を表現できず、古いブラウザで埋め込みが拒否される差が出る点も把握しておきます。
関連する対策との位置づけ
クリックジャッキング対策はフレーム制御が中心です。状態変更リクエストを扱うという点では、クロスサイトからの偽装リクエストを防ぐCSRF対策も欠かせませんが、これは枠内の正規ページ自身が有効なトークンを持つクリックジャッキングとは別の脅威への対策です。両者はそれぞれ異なる経路の意図しないリクエストを塞ぐ、独立した防御層として理解します。
あわせて読みたい
CSRFとは何か。仕組みからトークン・SameSite Cookieによる対策まで実務目線で解説
また、frame-ancestorsはContent-Security-Policyの一部であり、他のセキュリティHTTPレスポンスヘッダと合わせて設定することで運用が一貫します。ヘッダ全体の整理は次の記事にまとめています。
あわせて読みたい
セキュリティHTTPレスポンスヘッダで多層防御を固める方法
クリックジャッキング対策チェックリスト
- 重要ページのレスポンスにframe-ancestorsまたはX-Frame-Optionsが返っているか確認した
- 埋め込み不要なページはframe-ancestors 'none'を設定した
- 埋め込みが必要な場合は許可オリジンを'self'やホスト列挙で明示した
- 後方互換としてX-Frame-Options(DENYまたはSAMEORIGIN)を許可範囲に合わせて併記した
- frame-ancestorsとX-Frame-Optionsの許可範囲を突き合わせた(第三者を許可する構成では完全には整合できない点を把握した)
- 送金や権限変更など重要操作に確認ステップや再認証を設けた
- SameSite Cookieを設定し、CSRF対策は別の脅威への必須対策として別途実装した
- 検証環境でヘッダの適用と埋め込み可否を確認した
まとめ
クリックジャッキングは、標的サイトを透明なiframeで前面に重ね、見えている偽のUIをクリックしたつもりの操作を透明なiframe内の正規要素に実行させる攻撃で、CWE-1021に分類されます。被害はデータの読み取りよりも、利用者のセッションを使った意図しない操作の実行にあります。防御の中心は、CSPのframe-ancestorsディレクティブで枠内表示を許可するオリジンを宣言的に制限することです。frame-ancestorsを主対策とし、未対応ブラウザ向けにX-Frame-OptionsのDENYまたはSAMEORIGINを併記します。さらに重要操作には確認ステップや再認証を課し、SameSite Cookieを重ねることで、フレーム制御だけに依存しない多層の構えを取ります。なお、anti-CSRFトークンはクリックジャッキング自体を防ぐものではなく、別の脅威への必須対策として切り分けて実装します。
出典・参考
関連する記事
セキュリティHTTPレスポンスヘッダで多層防御を固める方法
CSPを中心に、HSTSやX-Content-Type-Options、クリックジャッキング対策、Referrer-PolicyといったセキュリティHTTPレスポンスヘッダの役割と設定を、開発者向けに整理します。
CSRFとは何か。仕組みからトークン・SameSite Cookieによる対策まで実務目線で解説
Webアプリの代表的脆弱性CSRFを、なぜ成立するのかという原理から、CSRFトークン(同期トークン・ダブルサブミット)とSameSite Cookieによる多層防御、よくある誤解までを実務目線で体系的に整理します。
XSS(クロスサイトスクリプティング)の仕組みと対策。反射型・格納型・DOM型を原理から整理
代表的なWeb脆弱性であるXSSを、なぜ起きるのかという原理から、反射型・格納型・DOM型の違い、想定される影響、根本対策である出力エスケープ(コンテキスト別エンコード)とCSPによる多層防御まで、実務目線で体系的に解説します。


