クリックジャッキングとは?対策に必須のセキュリティヘッダー
クリックジャッキングとは、攻撃者が用意した罠ページの上に、狙った正規サイトを透明な iframe で重ねて表示し、利用者に気づかれないままボタンやリンクをクリックさせる攻撃です。対策の基本は、自分のページを他のサイトの frame に埋め込ませないよう、HTTP レスポンスヘッダーで宣言することです。
現在の推奨は、CSP(Content-Security-Policy)の frame-ancestors ディレクティブです。古いブラウザへの備えとして X-Frame-Options を併記すると、設定漏れが起きにくくなります。どちらもサーバー設定の数行で入れられます。
この記事では、クリックジャッキングの仕組み、2 つのヘッダーの違い、X-Content-Type-Options・Referrer-Policy・Permissions-Policy など主要ヘッダーの役割、Apache と Nginx の設定例、CSP を壊さずに導入する手順を整理します。
クリックジャッキングとは?仕組みと被害の例
クリックジャッキング(clickjacking)は、UI リドレス攻撃とも呼ばれます。OWASP は、透明なフレームを重ねて、利用者が意図しない要素をクリックさせる攻撃として説明しています。
攻撃の流れ
攻撃者は、「当選おめでとうございます」「動画を再生」などのボタンを置いた罠ページを作ります。そのページに、狙った正規サイトを opacity:0 などで見えなくした iframe として重ね、ボタンの位置に「購入確定」「退会」「設定変更」といった正規サイト側のボタンが来るよう位置を合わせます。利用者は罠ページのボタンを押したつもりで、実際には正規サイトのボタンを押しています。
利用者がその正規サイトにログイン済みなら、ブラウザは Cookie を付けてリクエストを送るため、操作がそのまま有効になります。パスワードを盗むのではなく、ログイン中の権限を使って操作させる点が特徴です。
起こりうる被害
- ログイン中のアカウントでの意図しない設定変更・退会・送信
- SNS での「いいね」やフォローの強制
- 管理画面での操作(権限変更や削除ボタンなど)の誘発
入力欄にパスワードを打たせる型だけでなく、ボタン 1 回のクリックで完結する操作が狙われやすいと考えてください。確認画面が 1 クリックで進むサイトは特に注意が必要です。
X-Frame-Optionsとframe-ancestorsの違い
クリックジャッキング対策は、ページが frame に埋め込まれるのを許すかどうかをブラウザに伝えるヘッダーで行います。主な手段は 2 つあります。
X-Frame-Options(従来型)
MDN によると、指定できる値は DENY(どこからも埋め込み不可)と SAMEORIGIN(同一オリジンのみ可)です。かつて ALLOW-FROM という値がありましたが、現在は廃止されており、モダンブラウザでは無視されます。許可するサイトを個別に指定したい場合は X-Frame-Options では対応できません。また、<meta> タグでは効かず、HTTP ヘッダーで送る必要があります。
CSP の frame-ancestors(現在の推奨)
frame-ancestors は、そのページを <frame>・<iframe>・<object>・<embed> で埋め込んでよい親を指定します。'none'(誰にも許可しない。X-Frame-Options の DENY 相当)、'self'(同一オリジン)、特定のオリジン(https://www.example.org)を空白区切りで並べられます。入れ子の frame では、すべての祖先が条件に一致しないと読み込みがキャンセルされます。
注意点が 2 つあります。1 つは、frame-ancestors は default-src の影響を受けないことです。default-src 'none' を指定しても、frame-ancestors を書かなければ誰でも埋め込めます。もう 1 つは、<meta> 要素では使えないことです。OWASP のチートシートも、新規には frame-ancestors を優先し、X-Frame-Options は旧式として扱っています。
どちらを入れるべきか
実務上は両方を同じ意味で併記するのが無難です。たとえば同一オリジンのみ許可するなら、Content-Security-Policy: frame-ancestors 'self' と X-Frame-Options: SAMEORIGIN の組み合わせです。埋め込みを受け入れる外部サイトがある場合は、frame-ancestors で許可先を列挙し、X-Frame-Options は付けないか、外部許可と矛盾しない設定にします。矛盾した設定のときにどちらが採用されるかはブラウザの実装に依存しうるため、まず併記して両者の意味を揃えることが重要です。
主要なセキュリティヘッダーの役割一覧
セキュリティヘッダーは、ブラウザに「このサイトではこう動いてほしい」と伝えるレスポンスヘッダーです。クリックジャッキング対策以外にも、次のものがよく使われます。
X-Content-Type-Options: nosniff
ブラウザが中身から MIME タイプを推測(スニッフィング)するのをやめ、サーバーが宣言した Content-Type に従わせます。MDN によれば、script と style の読み込みでは MIME タイプが一致しない応答をブロックします。利用者がアップロードした text/plain が HTML として実行されるような事故を防ぐ目的です。値は nosniff のみ使います。
Referrer-Policy
リンク先や外部リソースへのリクエストに、参照元 URL(Referer)をどこまで含めるかを決めます。主な値は no-referrer、same-origin、strict-origin-when-cross-origin などです。MDN では、ブラウザの既定値は 2020 年 11 月以降 strict-origin-when-cross-origin と説明されています。URL に会員 ID やトークンが入るサイトでは、明示的に指定して意図を残しておくと安心です。
Permissions-Policy
カメラ、マイク、位置情報などのブラウザ機能を、そのページや埋め込みコンテンツが使えるかを制御します。() は全面無効、self は同一オリジンのみです。使わない機能を閉じるのが基本で、たとえば Permissions-Policy: camera=(), microphone=(), geolocation=() のように書きます。
Strict-Transport-Security(HSTS)
HTTPS での接続をブラウザに記憶させ、以後 HTTP でのアクセスを自動で HTTPS に切り替えさせます。詳しくは HSTS の解説記事をご覧ください。
Content-Security-Policy(CSP)
読み込みや実行を許可するリソースの出どころ(スクリプト、画像、フレームなど)を制限します。XSS の被害軽減に有効で、frame-ancestors もこの一部です。ただし導入の難易度が高いため、次の章で段階的な進め方を扱います。
Apache(.htaccess)とNginxの設定例
以下は同一オリジンのみ埋め込みを許可する例です。外部に埋め込ませたくない場合は 'self' を 'none'、SAMEORIGIN を DENY に置き換えてください。
Apache(.htaccess または仮想ホスト設定)
mod_headers が有効であることが前提です。always を付けると、エラー応答にもヘッダーが付きます。
<IfModule mod_headers.c>
Header always set Content-Security-Policy "frame-ancestors 'self'"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
</IfModule>Nginx(server ブロック内)
こちらも always を付けると、4xx・5xx 応答にもヘッダーが付きます。
add_header Content-Security-Policy "frame-ancestors 'self'" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;Nginx の add_header には、下位のブロック(location など)に add_header が 1 つでもあると、上位で定義したヘッダーが引き継がれなくなる仕様があります。location ごとにヘッダーを足している場合は、設定後に実際のレスポンスで確認してください。
設定後の確認方法
コマンドラインなら curl -sI https://example.com/ でレスポンスヘッダーを確認できます。ブラウザでは、開発者ツールの Network タブで対象のリクエストを選び、Response Headers を見ます。設定を変えたあとは、サーバーの再読み込み(Nginx は設定テスト後に reload)を忘れないようにしてください。
Content-Security-Policyを段階導入する方法(Report-Only)
CSP を一気に enforce(強制適用)すると、インラインスクリプトや外部の計測タグがブロックされ、サイトが壊れることがあります。そこで使うのが Content-Security-Policy-Report-Only ヘッダーです。W3C の CSP 仕様でも、ポリシーを強制せずその影響を監視するためのものとされています。違反はレポートされますが、リソースはブロックされません。
導入の手順
- frame-ancestors だけ先に入れる。埋め込みの制限は、他の読み込み制限より副作用が小さく、クリックジャッキング対策としてすぐ効きます。自サイトを自サイトの iframe で使っていないか確認したうえで入れます。
- Report-Only で本体のポリシーを試す。まず
default-src 'self'のような厳しめの案を Report-Only で流し、違反レポートから自サイトが何を読み込んでいるかを洗い出します。 - レポートを見てポリシーを調整する。必要な外部ドメイン(計測、広告、フォントなど)を許可リストに加えるか、インラインスクリプトを nonce やハッシュ方式に置き換えます。
- enforce に切り替える。違反がほぼ出なくなったら
Content-Security-Policyに名前を変えて適用します。
レポート送信の設定例
MDN が示す現行の方式は、Reporting-Endpoints ヘッダーで送信先を宣言し、ポリシー内の report-to で参照するものです。
Reporting-Endpoints: csp-endpoint="https://example.com/csp-reports"
Content-Security-Policy-Report-Only: default-src 'self'; report-to csp-endpointMDN は、report-to が全ブラウザで使えるようになるまでは、従来の report-uri も併記することを勧めています。レポートの受け口は自前で用意するか、レポート収集サービスを使います。
強制適用後の本命は、許可リスト方式ではなく nonce を使った strict CSP です。MDN の例では script-src 'nonce-{RANDOM}'; object-src 'none'; base-uri 'none' のように、リクエストごとに変わる乱数を使います。この移行は大規模で、テンプレート側の改修を伴います。
サイトスカウターのサーバー情報調査で診断される項目
サイトスカウターのサーバー情報調査は、対象 URL に HTTP GET を 1 回送って受け取ったレスポンスヘッダーなどから、セキュリティ面の項目を判定します。ポートスキャンや脆弱性探索は行わない、非侵襲な調査に限っています。
ヘッダーに関する判定
次の 6 つのヘッダーが、レスポンスに存在するかどうかを調べます。
- Strict-Transport-Security(HSTS)
- Content-Security-Policy
- X-Frame-Options
- X-Content-Type-Options
- Referrer-Policy
- Permissions-Policy
ヘッダーがあれば「OK」として値の先頭部分を表示し、なければ「警告」として設定の目安を表示します。ここで判定しているのは存在の有無であり、値の中身が適切かどうかまでは評価しません。たとえば frame-ancestors が書かれているか、CSP が十分に厳しいかは、診断結果とは別に人の目で確認してください。
ヘッダー以外の項目
HTTPS 対応の有無、サーバー証明書の有効性(期限切れ・自己署名・ホスト名不一致は NG、残り 30 日未満は警告)、Cookie の Secure・HttpOnly・SameSite 属性、Server や X-Powered-By ヘッダーによるバージョン情報の露出、DNS ブラックリストへの掲載も調べます。クリックジャッキング対策としては、OWASP が補助策に挙げる SameSite 属性(Cookie が別サイトの iframe 経由で送られるのを抑える)の有無も、Cookie の項目から確認できます。
対策の優先順位とよくある落とし穴
ひととおり理解したら、次の順で進めると失敗しにくくなります。
- ログイン画面・会員ページ・決済や設定変更のページを含む全体に、frame-ancestors と X-Frame-Options を入れる
- X-Content-Type-Options と Referrer-Policy を入れる(副作用が小さい)
- Permissions-Policy で使わない機能を閉じる
- HSTS を段階的に導入する
- CSP の本体を Report-Only から始める
落とし穴
- meta タグで設定してしまう。X-Frame-Options も frame-ancestors も meta では効きません。
- 自社の埋め込み機能を壊す。自社の別ドメインや、取引先に埋め込んでもらうウィジェットがある場合は、frame-ancestors に許可先を入れる必要があります。
- JavaScript のフレーム破りに頼る。OWASP は、古い frame-busting スクリプトはモダンな攻撃手法で回避されうるため避けるよう述べています。ヘッダーが基本です。
- 静的ファイルや CDN 経由の応答に付かない。アプリケーション側でヘッダーを付けていても、静的ファイルの配信経路や CDN が別設定だと抜けます。
ヘッダーは「入れて終わり」ではありません。サーバーの入れ替えや CDN の追加で設定が消えることがあるため、変更のたびに実際のレスポンスを確認する習慣をつけましょう。
よくある質問
クリックジャッキングとは何ですか?
攻撃者の罠ページに、正規サイトを透明な iframe として重ね、利用者に意図しないクリックをさせる攻撃です。ログイン中の権限で操作が実行される点が特徴です。
X-Frame-Options と CSP の frame-ancestors はどちらを使うべきですか?
現在の推奨は CSP の frame-ancestors です。許可先を個別に指定でき、X-Frame-Options の ALLOW-FROM は廃止されています。旧環境への備えとして、同じ意味で X-Frame-Options を併記するのが実務上無難です。
meta タグでクリックジャッキング対策はできますか?
できません。X-Frame-Options も frame-ancestors も、HTTP レスポンスヘッダーで送る必要があります。
CSP を入れるとサイトが壊れませんか?
強制適用するとインラインスクリプトや外部タグがブロックされる場合があります。まず Content-Security-Policy-Report-Only で違反を収集し、調整してから適用してください。frame-ancestors だけ先に入れる方法もあります。
サーバー情報調査はヘッダーの中身まで評価しますか?
いいえ。6 種類のセキュリティヘッダーが存在するかどうかを判定しており、値が十分に厳しいかまでは評価しません。
出典・参考資料
最終確認日:2026-10-06。制度・仕様は変更されることがあるため、実施前に各一次情報をご確認ください。
- MDN: X-Frame-Options
- MDN: CSP frame-ancestors
- MDN: Content Security Policy (CSP) ガイド
- OWASP Clickjacking Defense Cheat Sheet
- W3C Content Security Policy Level 3
- MDN: X-Content-Type-Options
- MDN: Referrer-Policy
- MDN: Permissions-Policy