結論(クリックジャッキング対策を全HTMLへ適用)
クリックジャッキング対策を全HTMLへ適用とは、ページを他サイトのiframeなどに表示させない指示を、すべてのHTML応答に付けることです。X-Frame-OptionsのDENY/SAMEORIGIN、またはCSPのframe-ancestorsを、トップページだけでなく下層ページやエラーページにも付けます。攻撃者が狙うのは申請送信や設定変更のボタンがある下層ページのため、Webサーバーの共通設定で全HTMLに一律付与するのが確実です。
この記事のポイント
- クリックジャッキングは、正規サイトを透明なiframeで重ね、利用者に別のボタンを押しているつもりで正規サイトの操作をさせる攻撃です。
- X-Frame-OptionsはHTTPヘッダーでのみ有効で、metaタグでは効きません。ALLOW-FROMは現行ブラウザで保護になりません。
- 強制モードのCSPにframe-ancestorsがあると、ブラウザはX-Frame-Optionsを無視してCSPで判定します。
- セキュリティAIチェッカーはIPAの推奨に沿いX-Frame-Optionsだけでも合格とし、1ページでも保護がなければ×と判定します。
- 埋め込みが不要なサイトは、frame-ancestors 'self'とX-Frame-Options: SAMEORIGINの併記が基本です。
| 診断項目名 | クリックジャッキング対策を全HTMLへ適用 |
|---|---|
| 項目ID | crawl.frame-coverage |
| 分類 | セキュリティヘッダー |
| 重大度・配点の重み | 重要(high) 重み 3 |
| 関連する標準・ガイドライン | IPA「安全なウェブサイトの作り方」1.9 クリックジャッキング(根本的解決 9-(i)-a:X-Frame-Options の出力)、OWASP ASVS 5.0.0 V3.4.6(全応答で CSP frame-ancestors を使用。X-Frame-Options は旧式とされる、L2)、OWASP WSTG-CLNT-09(Clickjacking)、HTML Living Standard「X-Frame-Options」の処理モデル、RFC 7034、CWE-1021(Improper Restriction of Rendered UI Layers or Frames) |
クリックジャッキング対策を全HTMLへ適用とは
クリックジャッキング対策を全HTMLへ適用とは、ページを他サイトの枠(frame・iframe 等)の中に表示させないための指示(X-Frame-Options の DENY/SAMEORIGIN、または CSP の frame-ancestors)を、トップページだけでなく下層ページやエラーページを含むすべてのHTML応答に付けることです。
クリックジャッキングは、攻撃者のページに正規サイトを透明な iframe で重ね、利用者に別のボタンを押しているつもりで正規サイト上の操作をさせる攻撃です。対策は、ページを他サイトの枠の中に表示させないよう、ブラウザに指示することです。
セキュリティAIチェッカーのこの項目は、トップページと巡回した下層ページの「すべてのHTML応答」に、ブラウザが実際に有効と扱う埋め込み制限(CSP の frame-ancestors、または X-Frame-Options の DENY/SAMEORIGIN)があるかを確認します。IPA の推奨する X-Frame-Options でも合格とする、互換性重視の項目です。より厳格な ASVS 5.0.0 の要件(frame-ancestors 必須)は、別項目「CSP frame-ancestorsを全HTMLへ適用」で評価します。トップページ単体の判定は「クリックジャッキング対策」で行い、このページは全HTMLへの適用範囲に絞って解説します。
クリックジャッキング対策の2つの仕組みとブラウザの判定
X-Frame-Options と CSP frame-ancestors
| 方式 | 指定例 | 特徴 |
|---|---|---|
| X-Frame-Options | X-Frame-Options: DENY / SAMEORIGIN | 古くから全主要ブラウザが対応。許可先を個別指定できない |
| CSP frame-ancestors | Content-Security-Policy: frame-ancestors 'self' https://partner.example.jp | 許可する埋め込み元を複数指定できる。CSP Level 2 以降 |
ブラウザの判定手順(HTML Living Standard)
HTML 仕様の「X-Frame-Options への準拠の確認」の手順は次のとおりです。
- 強制モード(Report-Only でない)のCSPに
frame-ancestorsがあれば、X-Frame-Options は無視し、CSP で判定する。 - X-Frame-Options の値をカンマで分割し、小文字化して重複を除いた集合を作る。
- 集合の要素が2つ以上で、
deny・allowall・sameoriginのいずれかを含む場合は、表示を拒否する(設定の混乱とみなし安全側に倒す)。 - 要素が2つ以上で上記を含まない場合は、ヘッダーがないものとして扱う。
- 要素が1つで
denyなら拒否、sameoriginなら全祖先が同一オリジンのときだけ表示する。 - それ以外(
ALLOW-FROMなど無効な単独値)はヘッダーがないものとして扱う。
このため、WebサーバーとCMSの両方が付与して X-Frame-Options: SAMEORIGIN, SAMEORIGIN となった応答は、重複が除かれて sameorigin として有効です。ALLOW-FROM は HTML 仕様で「実装しない」とされ、現行ブラウザでは保護になりません。
クリックジャッキング対策についてよくある誤解
- 「
<meta http-equiv="X-Frame-Options">で設定できる」:X-Frame-Options はHTTPヘッダーでのみ有効です。CSP のframe-ancestorsも<meta>では無視されます(CSP3)。 - 「JavaScript のフレーム破り(
if (top !== self))で十分」:sandbox 属性付き iframe などで回避される場合があり、OWASP も主対策としては推奨していません。 - 「トップページだけで良い」:攻撃者が狙うのは、申請送信・設定変更・ログアウトなどのボタンがある下層ページです。
クリックジャッキング対策を全HTMLへ適用の診断基準(セキュリティAIチェッカー)
取得対象
- トップページ(最終応答)と、巡回で発見した同一オリジンの下層ページのうち最大2ページ(GET、リダイレクト最大2回、応答上限180KB、取得失敗ページは除外)。
- そのうち
Content-Typeがtext/htmlの応答、または本文に<htmlを含む応答を「HTML応答」として評価します。エラーページ(404等)もHTMLなら対象です。
「保護あり」とする条件
各HTML応答について、次の順で判定します。
Content-Security-Policyヘッダー(複数ある場合はカンマで連結した値)にframe-ancestorsディレクティブがある場合は、最初に現れたframe-ancestorsの値を空白で区切ったトークン単位で評価します。値が空でなく、*・https:・http:(スキームだけの指定)のいずれのトークンも含まなければ保護あり、1つでも含むか空なら保護なし(このとき X-Frame-Options はブラウザに無視されるため評価しない)。'self' *のように他の値と併記していても保護なしです。frame-ancestorsがない場合は、X-Frame-Optionsの値をカンマで分割・小文字化した集合にdenyまたはsameoriginが含まれれば保護あり(HTML 仕様の処理に沿った判定です。ALLOWALLと別の無効値だけを併記した応答は、ブラウザは安全側で拒否しますが、意図した保護ではないため保護なしとします)。- いずれにも該当しなければ保護なし。
Content-Security-Policy-Report-Only と <meta> によるCSPは、ブラウザが埋め込み制限として強制しないため評価しません。
判定条件
| 判定 | 条件 | 得点係数 |
|---|---|---|
| ○ 問題なし(pass) | 評価したすべてのHTML応答で保護あり | 1 |
| × 要改善(fail) | HTML応答のうち1つでも保護なし | 0 |
| 対象外(na) | HTML応答が1つもない | 計算から除外 |
重み3のため、× の場合は3点分を失います。根拠欄に「何ページ中何ページで不足か」を表示します。
自治体サイトでの判定例
| 構成 | 判定 |
|---|---|
.htaccess で Header always set X-Frame-Options "SAMEORIGIN" を全体に設定 | ○ |
| CMSのページは X-Frame-Options 付きだが、別システムの施設予約ページ(同一ドメイン配下)には何もない | × |
地図ページを他自治体サイトに埋め込ませるため X-Frame-Options: ALLOW-FROM https://... を設定 | ×(現行ブラウザで無効。frame-ancestors で許可先を列挙する必要があります) |
X-Frame-Options: SAMEORIGIN, SAMEORIGIN(二重付与) | ○(ただし付与箇所の一本化を推奨) |
クリックジャッキング対策が一部のページにないとどんなリスクがあるか
- 意図しない操作:ログイン中の利用者に、電子申請の送信、メール配信設定の変更、公開範囲の変更などをクリックだけで実行させられます。IPA は、脅威はマウス操作だけで実行できる処理に限られる点以外は CSRF と同様だと説明しています。
- 入力の誘導:ドラッグ&ドロップや入力欄を重ねることで、利用者に情報を入力させる手法も知られています。
- 実例:2008年に Robert Hansen と Jeremiah Grossman が、Adobe Flash Player の設定画面を重ねてカメラ・マイクを許可させる手法を公表し、クリックジャッキングという名称が広まりました。2009年には Twitter で、クリックするとそのメッセージを自分のアカウントで投稿してしまう「Don't Click」攻撃が拡散しました。
- 信頼の悪用:自治体の正規ドメインのページが偽サイトの中に表示されると、利用者は正規の操作だと信じやすくなります。
クリックジャッキング対策を全HTMLへ適用する設定方法(Apache・nginx・IIS・Next.js)
基本方針
- 埋め込みが不要なサイトは、全HTML応答に
frame-ancestors 'self'(または'none')とX-Frame-Options: SAMEORIGIN(またはDENY)を併記します。CSP 対応ブラウザは frame-ancestors を、古いブラウザは X-Frame-Options を使います。 - 他サイトへの埋め込みを許可するページだけ、frame-ancestors で許可先を列挙し、そのページでは X-Frame-Options を外します(併記すると CSP 対応ブラウザでは CSP が優先されますが、非対応ブラウザでは表示できなくなります)。
Apache(.htaccess)
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Content-Security-Policy "frame-ancestors 'self'"
</IfModule>
既にCSPを設定している場合は、既存の Content-Security-Policy の値に ; frame-ancestors 'self' を追記します。set で別の値を上書きすると既存のCSPが失われます。
nginx
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Content-Security-Policy "frame-ancestors 'self'" always;
location ブロック内に別の add_header があると上位の設定は継承されません。共通ヘッダーを include ファイルにまとめて各ブロックで読み込みます(nginx 1.29.3 以降は add_header_inherit merge; でも継承できます)。
IIS(web.config)
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="SAMEORIGIN" />
<add name="Content-Security-Policy" value="frame-ancestors 'self'" />
</customHeaders>
</httpProtocol>
</system.webServer>
Next.js(Vercel)
// next.config.js
module.exports = {
async headers() {
return [{
source: "/:path*",
headers: [
{ key: "X-Frame-Options", value: "SAMEORIGIN" },
{ key: "Content-Security-Policy", value: "frame-ancestors 'self'" },
],
}];
},
};
全HTMLに付いているかの確認方法
for u in / /kurashi/ /no-such-page; do
echo "== $u"
curl -s -o /dev/null -D - "https://www.example.lg.jp$u" | grep -iE '^(x-frame-options|content-security-policy):'
done
ブラウザで別オリジンのテストページに <iframe src="https://www.example.lg.jp/"> を置き、表示が拒否されることも確認します。
サイトを壊さないための注意点(ガードレール)
- 導入前に、自サイトを他サイト(県のポータル、観光協会、議会中継、地図サービス等)へ iframe で埋め込ませていないかを確認します。埋め込みが必要なページに
DENYを付けると表示されなくなります。 - 自サイト内で自分のページを iframe 表示している場合(印刷用プレビュー、CMS の編集画面等)は
DENYではなくSAMEORIGIN/'self'を使います。
よくある質問(FAQ)
クリックジャッキング対策はトップページだけでよいですか?
不十分です。攻撃者が狙うのは、申請送信・設定変更・ログアウトなどのボタンがある下層ページです。404などのエラーページも含め、すべてのHTML応答に付けてください。
X-Frame-Optionsはmetaタグで設定できますか?
できません。X-Frame-OptionsはHTTPヘッダーでのみ有効です。CSPのframe-ancestorsも、metaタグで指定した場合は無視されます(CSP3)。
X-Frame-Options: ALLOW-FROMで特定サイトだけ許可できますか?
できません。ALLOW-FROMはHTML仕様で「実装しない」とされ、現行ブラウザでは保護になりません。特定サイトへの埋め込みを許可する場合は、CSPのframe-ancestorsで許可先を列挙します。
X-Frame-Options: SAMEORIGIN, SAMEORIGINと二重になっていますが有効ですか?
有効です。HTML仕様の処理では値をカンマで分割し重複を除くため、sameoriginとして扱われます。ただし付与箇所の一本化を推奨します。
JavaScriptのフレーム破りで代用できますか?
if (top !== self) のようなフレーム破りは、sandbox属性付きのiframeなどで回避される場合があり、OWASPも主対策としては推奨していません。HTTPヘッダーで対策してください。
X-Frame-Optionsだけで合格になりますか?
この項目ではIPAの推奨に沿ってX-Frame-OptionsのDENY/SAMEORIGINだけでも合格です。ただしOWASP ASVS 5.0.0はframe-ancestorsの使用を求めており、そちらは「CSP frame-ancestorsを全HTMLへ適用」で評価され、X-Frame-Optionsだけでは不合格になります。
自サイト内でiframeを使っている場合はどう設定しますか?
印刷用プレビューやCMSの編集画面などで自分のページをiframe表示している場合は、DENYではなくSAMEORIGIN/'self'を使います。
この項目を含む127項目を、URLを入れるだけで無料診断します。
参考資料
- IPA「安全なウェブサイトの作り方」1.9 クリックジャッキング
- HTML Living Standard(X-Frame-Options の処理)
- OWASP ASVS 5.0.0 V3 Web Frontend Security(V3.4.6)
- OWASP Clickjacking Defense Cheat Sheet
- W3C Content Security Policy Level 3
- RFC 7034 HTTP Header Field X-Frame-Options
- MDN X-Frame-Options
- MDN CSP: frame-ancestors
- Apache HTTP Server mod_headers
- nginx ngx_http_headers_module
- Next.js headers