astris.design

クリックジャッキング対策はCSPのframe-ancestors推奨、X-Frame-Optionsはレガシー

クリックジャッキング対策には、X-Frame-Optionsヘッダによる方法と、CSPのframe-ancestorsディレクティブによる方法があります。しかし、X-Frame-Optionsヘッダではなく、CSPのframe-ancestorsディレクティブを使用すべきです。その理由について解説します(サンプルあり)。

【目次・クリックジャッキング対策で推奨される方法】

クリックジャッキングとは?

クリックジャッキングとは、罠サイトのボタンやリンクをユーザにクリックさせることで、悪意ある処理を実行させる攻撃です。
クリックジャッキングの手口は、簡単に言えば、iframeを悪用したものです。
iframeを使用して罠サイトに攻撃対象のページを埋め込み、偽のボタンを重ねることで、攻撃対象のページのボタンをクリックさせるという仕組みです。
そのため、iframeの使用を制限することが、クリックジャッキング対策となります。
iframeの使用を制限する方法として、X-Frame-Optionsヘッダと、CSPのframe-ancestorsディレクティブがあります。
しかし、X-Frame-Optionsヘッダは、次節の理由であまり使用すべきではありません。


X-Frame-Options:非推奨・レガシー

X-Frame-Optionsヘッダは、iframeによるページの埋め込みを制限するためのヘッダです。
X-Frame-Optionsヘッダには、以下の指定をすることができます。

X-Frame-Optionsヘッダの指定
指定制限
DENY全てのオリジンに対して、フレーム内の埋め込みを禁止
SAMEORIGIN同一オリジンにのみ、フレーム内の埋め込みを許可
ALLOW-FROM origin指定したオリジンにのみ、フレーム内への埋め込みを許可

サンプル

x-frame-options.js
import helmet from "helmet";
app.use(
  helmet({
    xFrameOptions: { action: "sameorigin" },
  }),
);

ただ、以下の理由でX-Frame-Optionsヘッダは、あまり使用するべきではありません。

  • CSPのframe-ancestorsディレクティブに取って代わられた、レガシーなヘッダーである。
  • ALLOW-FROMをサポートしていないブラウザが多い(2023年8月時点)。

MDN Web DocsのX-Frame-Optionsのブラウザ対応表で確認すると、多くのブラウザでALLOW-FROMが非サポートとなっています。

実際、ChromeとEdgeの最新バージョンで確認したところ、SAMEORIGINとDENYは機能したのですが、ALLOW-FROMは正しく機能しませんでした(2023年8月)。
ALLOW-FROMを指定すると、エラーとなり、指定したオリジン以外でもiframeによる埋め込みが可能となりました。
Invalid 'X-Frame-Options' header encountered when loading 'http://localhost:3000/': 'ALLOW-FROM http://xxx:3000' is not a recognized directive. The header will be ignored.

以上より、X-Frame-OptionsヘッダのALLOW-FROMは、指定してはいけません。
SAMEORIGINとDENYは、CSPに対応していない古いブラウザ対応として、使用することが考えられます。


CSPのframe-ancestorsディレクティブ:推奨

CSP(Content-Security-Policy)とは、ブラウザのセキュリティ機能です。
Content-Security-Policyヘッダにディレクティブを指定することで、セキュリティ強化につながる制限を加えることができます。
CSPのframe-ancestorsディレクティブでは、X-Frame-Optionsと同様、iframeによるページの埋め込みを制限することができます。

CSPのframe-ancestorsディレクティブの指定
指定制限
frame-ancestors 'none'全てのオリジンに対して、フレーム内の埋め込みを禁止
frame-ancestors 'self'同一オリジンにのみ、フレーム内の埋め込みを許可
frame-ancestors origin指定したオリジンにのみ、フレーム内への埋め込みを許可

サンプル

frame-ancestors.js
import helmet from "helmet";
app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        "frame-ancestors": ["'self'", "example.com"],
      },
    },
  }),
);

ChromeとEdgeで確認したところ、CSPのframe-ancestorsディレクティブは、正しく機能していました。


まとめ

クリックジャッキング対策の方法について、解説しました。
クリックジャッキング対策で、iframeの制限を行う場合は、CSPのframe-ancestorsディレクティブを使用しましょう。
X-Frame-Optionsヘッダを紹介するブログや書籍もありますが、X-Frame-Optionsヘッダはレガシーな仕様で、ALLOW-FROMの指定が正しく機能しません(2023年8月時点)。
X-Frame-Opionsヘッダ(SAMEORIGINとDENY)は、CSPに対応していない古いブラウザ対応に使用するといいでしょう。

  • CSPのframe-ancestorsディレクティブ:推奨
  • X-Frame-Optionsヘッダ:非推奨・レガシー(CSPに対応していない古いブラウザ用)