WEB SECURITY / UI REDRESS
クリックジャッキングとは?
iframeとHTTPヘッダーの対策を体系的に理解する
公開日:2026-10-10
「プレゼントが当たりました」というボタンをクリックしたつもりが、実際にはログイン済みサービスの設定変更ボタンを押していた――そんな画面のだましを利用するのがクリックジャッキング(Clickjacking)です。暗号化通信を使っていても起こり得るため、ブラウザに『この画面を他サイトへ埋め込んでよいか』を伝える仕組みが重要になります。
身近な例 → HTMLとiframe → CSSの重なり → オリジン → HTTPレスポンスヘッダー → X-Frame-Options → CSP frame-ancestors → Cookie・HSTSの役割分担 → 実装と検証 → 操作ラボ。Webセキュリティの他の脅威とも比較します。
1. どんなときに被害が起きる? 日常の画面で考える
ネット通販サイトの住所変更画面、SNSの公開範囲設定、企業の管理画面など、ログイン済みならボタン一つで操作できるページが標的になることがあります。攻撃者は、自分のページに本来のページを読み込み、透明にしたうえでユーザーが押したくなる場所へ重ねます。
| 用語・対策 | 何を制御するか | 実際の例・注意 |
|---|---|---|
| 会員サイトのプロフィール設定 | 偽のキャンペーンボタンの下に『情報公開』などの操作を重ねる | 実際に処理されるかは認証状態や追加確認の有無にも依存 |
| SNSの操作画面 | 無関係な画像や動画の再生ボタンに見せる | 投稿や設定の意図しない操作を誘う例 |
| 社内システムの承認画面 | 業務画面を外部サイトにiframeで埋め込ませない | 管理者操作に再認証・承認フローを要求するのも重要 |
| 外部サイトへの地図・動画の埋め込み | 正当な埋め込みを許容するケース | iframeを全否定せず、必要なページと許可元を区別する |
2. Webページの基本:HTML・iframe・CSSの役割
HTMLは文章やボタンなどの構造を記述し、CSSは位置・色・透明度を指定します。iframe(インラインフレーム)は別のWebページを現在のページ内に表示する要素です。たとえばブログに地図や動画プレイヤーを埋め込むときにも使われます。
<!-- 正当なiframeの例:地図などを自分のページ内に表示 -->
<iframe src="https://maps.example.test/embed"
title="アクセスマップ"></iframe>iframeには独立したページが読み込まれます。攻撃者が別サイトのページを重ねようとしても、対象ページが埋め込みを拒否するレスポンスヘッダーを返せば、対応ブラウザは表示を拒否します。
- 利用者が親ページを開き、HTMLのiframe要素が読み込まれる。
- ブラウザが子ページのURLへ別途リクエストを送る。
- 子ページのHTTP応答にあるX-Frame-OptionsやCSP frame-ancestorsをブラウザが評価して表示可否を決める。
3. 攻撃はどう成立する? ノード図で3者を理解
攻撃では透明化のためにCSSのopacity(不透明度)や位置指定が悪用されます。たとえば前面の透明フレームと背面の『抽選ボタン』を重ねると、見た目のボタンと実際にクリックを受けるページが一致しません。
- 攻撃者が偽の説明・ボタンを置き、正規サイトの操作画面を透明iframeで重ねようとする。
- 利用者は背面のボタンをクリックしたつもりになる。
- 子ページの埋め込みが許され、条件がそろうと、正規サービスへの意図しない操作が発生し得る。
4. オリジンとは? URLのどこが同じなら『同一』か
Origin(オリジン)は、URLのスキーム(httpsなど)・ホスト名・ポート番号の組です。たとえばhttps://account.example.testとhttps://shop.example.testは、同じ組織のドメイン配下でも別オリジンです。
| 用語・対策 | 何を制御するか | 実際の例・注意 |
|---|---|---|
| https://account.example.test/profile | 基準となるオリジン | https + account.example.test + 443 |
| https://account.example.test/settings | 同一オリジン | パスだけが異なる |
| https://shop.example.test | 別オリジン | ホスト名が異なる |
| http://account.example.test | 別オリジン | スキームが異なる |
| https://account.example.test:8443 | 別オリジン | ポートが異なる |
後述するSAMEORIGINやCSPの'self'を理解するときの土台です。CookieのSameSiteは同一オリジンとは異なる『サイト』の概念に基づいて判定するので、名前が似ていても混同しないでください。
5. X-Frame-Options:埋め込みを拒否するHTTPレスポンスヘッダー
X-Frame-Options(XFO)は、ページを他のページのフレーム内に表示させてよいかを、子ページ自身がブラウザへ伝えるHTTPレスポンスヘッダーです。攻撃者側のHTMLを書き換えるのではなく、守る側のサーバーから返すことがポイントです。
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
X-Frame-Options: DENY| 用語・対策 | 何を制御するか | 実際の例・注意 |
|---|---|---|
| X-Frame-Options: DENY | 同じオリジンを含む全フレームへの埋め込みを拒否 | 設定変更・決済など外部埋め込み不要なページに適する |
| X-Frame-Options: SAMEORIGIN | 同一オリジンのフレームだけ許す | 自社サービス内での埋め込みが必要な場合 |
| ALLOW-FROM(旧指定) | 古い仕様の指定で、現代の主要ブラウザでは非対応 | 外部の特定サイトだけを許したい場合はCSPを使う |
6. 現代的な対策:CSPのframe-ancestors
CSP(Content Security Policy:コンテンツセキュリティポリシー)は、ブラウザにコンテンツの読み込み・埋め込みの制限を伝えるセキュリティポリシーです。frame-ancestorsディレクティブは、『このページを誰が埋め込んでよいか』を指定します。
# 一切のフレーム埋め込みを拒否
Content-Security-Policy: frame-ancestors 'none';
# 同一オリジンのみ許可
Content-Security-Policy: frame-ancestors 'self';
# 自社と明示的に許した提携先のみ許可
Content-Security-Policy: frame-ancestors 'self' https://partner.example.test;| 用語・対策 | 何を制御するか | 実際の例・注意 |
|---|---|---|
| frame-ancestors | どの親ページがこのページを埋め込めるか | クリックジャッキング対策の中心。全祖先フレームが評価対象 |
| frame-src | このページがどのURLをiframeとして読み込めるか | 向きが逆。自分が『読み込む側』の制御 |
| default-src | CSP内で他の一部の取得系ディレクティブに対する既定値 | frame-ancestorsへはフォールバックしない |
| X-Frame-Options | 古くからある埋め込み制御ヘッダー | CSPによる制御と併用することがある |
対応ブラウザでは、強制適用のCSPにframe-ancestorsが含まれるとX-Frame-Optionsより優先されます。frame-ancestorsもHTTPレスポンスヘッダーで設定します。CSPの<meta>では有効にできません。
7. Cookie・HttpOnly・Secure・SameSite・HSTSを混同しない
Webセキュリティの設定は、名前が似ていても守る対象が違います。個々の対策がクリックジャッキングを直接防ぐか、それとも別の被害を減らすかを区別しましょう。
| 用語・対策 | 何を制御するか | 実際の例・注意 |
|---|---|---|
| HttpOnly(Cookie属性) | JavaScriptからのCookie読み取りを制限 | XSSによるCookieの窃取リスクを低減。フレーム埋め込み自体は止めない |
| Secure(Cookie属性) | HTTPS接続にCookie送信を限定 | HTTPでのCookie送信を防ぐ。クリック対象の偽装には無関係 |
| SameSite=Lax / Strict | クロスサイトリクエストでのCookie送信を制限 | クロスサイトiframeの認証Cookie送信を抑える補助策(フレーム表示禁止とは別) |
| HSTS(Strict-Transport-Security) | 対応ブラウザにHTTPS接続を強制 | HTTPへのダウングレードを減らすが、クリックジャッキングは止めない |
| X-Frame-Options / CSP frame-ancestors | ページがiframe等へ埋め込まれることを制御 | フレーム型クリックジャッキングへの直接的な対策 |
Set-Cookie: session=...; Secure; HttpOnly; SameSite=Lax
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Frame-Options: DENY
Content-Security-Policy: frame-ancestors 'none';8. 操作ラボ:設定を変えると表示可能な親ページは変わる
埋め込み元が攻撃者・同一オリジン・提携先の場合を切り替えます。クリックの重なりを模式的に表示しながら、XFOとCSPのルールがどこまで許可するかを確認してください。
画面の重ね合わせと埋め込みポリシーを体験
これは外部ページや本物のログイン画面を読み込まない安全な模式図です。透明なフレームはCSSで再現し、ヘッダーの判定は教材用ロジックで模擬します。
親ページ:https://gift.attacker.test
抽選キャンペーン
当選確認ボタンに見える
重ねたレイヤーは学習用の図解です。実際のクリックジャッキングでは透明フレームのクリック可能な要素に入力が届くよう配置されます。
ブラウザは埋め込みを許可
(フレーム埋め込み制限ヘッダーなし)
ページが埋め込みを拒否しない。攻撃者のiframe表示が成立するおそれがある。
Cookie参考:このモデルではクロスサイト埋め込み時、SameSite=Laxなら通常の認証Cookieは送られません(トップレベル遷移等は別)。Cookieが送信されないこととiframeの埋め込み禁止は別の保護層です。現在の想定Cookie送信:あり。同一サイトと同一オリジンは異なる概念です。
注意:実際には子ページのHTTP応答に設定したX-Frame-Options/CSPがブラウザに評価されます。実験の結果は学習用の簡略化であり、ブラウザの全挙動を再現しません。
9. サーバー実装ではどこに設定する?
Next.jsなどで保護する場合、対象ルートのHTTPレスポンスヘッダーとして設定します。アプリの中に埋め込みが必要なページがある場合は、全ページで一律にDENYする前に要件を整理しましょう。
// next.config.ts の例(用途に合わせてパスや値を調整)
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
async headers() {
return [{
source: "/(.*)",
headers: [
{ key: "X-Frame-Options", value: "DENY" },
{ key: "Content-Security-Policy", value: "frame-ancestors 'none';" },
],
}];
},
};
export default nextConfig;これは必要最小限の概念例です。既存のCSPヘッダーがあるサイトでは、既存ポリシーを置き換えて他の制限を消さないようにframe-ancestorsを統合してください。CDNやリバースプロキシがヘッダーを追加・変更する構成では、実際の公開レスポンスを確認します。
- ブラウザが保護対象のページを要求する。
- WebサーバーやCDNなどがX-Frame-OptionsとCSPを付けて応答する。
- ブラウザが祖先フレームのオリジンとヘッダーを照合し、埋め込み可否を判断する。
# レスポンスヘッダー確認例
curl -I https://account.example.test/settings
# 確認したい項目
# X-Frame-Options: DENY
# Content-Security-Policy: frame-ancestors 'none';10. XSS・CSRF・フィッシングとの違い
| 用語・対策 | 何を制御するか | 実際の例・注意 |
|---|---|---|
| クリックジャッキング | 見た目と実際のクリック対象をずらす | フレーム埋め込み制御・重要操作の確認 |
| XSS | 悪意あるスクリプトをサイト上で実行させる | 出力エスケープ・安全なDOM操作・CSPなど |
| CSRF | 利用者の認証状態を悪用し意図しないリクエストを送らせる | CSRFトークン・SameSite・Origin検証など |
| フィッシング | 偽サイトや偽メールで認証情報や金銭をだまし取る | URL確認・フィッシング耐性のある認証等 |
| 通信の盗聴・改ざん | ネットワーク上の通信内容を不正に取得・変更 | HTTPS・証明書の検証・HSTSなど |
クリックジャッキングとCSRFは、ともに「利用者が望まない操作」の問題ですが、前者は画面上のクリック誘導が中心です。フレーム禁止だけではCSRF全般は防げませんし、CSRFトークンを使っていても、正規ページの操作をクリックさせる攻撃には別の防御が必要です。
11. 運用チェックリストと限界
- 重要な操作画面・管理画面に、原則として
frame-ancestors 'none'などの明示的な制限を設定する。 - 埋め込みが必要な画面は親ページを列挙し、最小限の許可元だけを指定する。
- HTTPレスポンスヘッダーを確認し、実際に別オリジンからのiframe表示が拒否されるかテストする。
- Cookieに
Secure、HttpOnly、適切なSameSiteを設定し、多層防御にする。 - 高リスク操作には、対象内容の再確認、再認証、サーバー側の厳格な認可を用意する。
- iframe以外のUI誘導や別ウィンドウを使う手口もあるため、フレーム制限だけを万能と考えない。
12. よくある疑問
A. いいえ。地図やダッシュボードの埋め込みなど正当な用途があります。『何を・誰に埋め込ませるか』を設計し、必要に応じてCSPの許可元を限定します。
A. いいえ。frame-srcは自ページが読み込むフレーム先の制御。自ページが他ページに埋め込まれることを制御するのはframe-ancestorsです。
A. 許可元を細かく指定したい場合も含めてCSPのframe-ancestorsを中心に考え、互換性などに応じてX-Frame-Optionsを併記します。両者が矛盾する設定にならないようにします。
A. できません。HTTPSは通信路を守り、WAFは主にHTTP通信を検査します。ブラウザの埋め込み可否を制限するのは別の仕組みです。
参考資料・仕様
実装時はブラウザ仕様とOWASPの推奨を確認してください。特にCSPとX-Frame-Optionsの優先関係、SameSiteの制約、非対応の旧指定に注意が必要です。
- Clickjacking Defense Cheat Sheet(OWASP)
- X-Frame-Options header(MDN Web Docs)
- CSP frame-ancestors(MDN Web Docs)
- Set-Cookie header(MDN Web Docs)
- Strict-Transport-Security header(MDN Web Docs)
- Content Security Policy Cheat Sheet(OWASP)