すべての解説
深刻度:中セキュリティヘッダー

Clickjackingと X-Frame-Options:ページをiframeの外に保つ

clickjackingは、あなたのページを攻撃者が管理するサイト上の透明なiframeに読み込ませ、隠したコントロールをユーザーにクリックさせる手口です。X-Frame-Options——または最新のCSPの frame-ancestors ディレクティブ——は、あなたのページの埋め込みを拒否するようブラウザに指示し、この攻撃を完全に封じます。

これは何か

clickjacking攻撃は、攻撃者のページ上の見えない、または半透明のiframeにあなたのサイトをフレーム化することで成り立ちます。被害者はおとりのコンテンツを見て、無害に見えるボタンをクリックします。すると、隠れたiframeがあなたのページ上の本物のクリック——送金、設定変更、OAuthの許可——を、ユーザーに気づかせないまま奪います。

X-Frame-Options は、2つの有用な値を持つHTTP応答ヘッダーです。DENY(誰による埋め込みも拒否)と SAMEORIGIN(自分のオリジンのページからの埋め込みのみ許可)です。CSPの frame-ancestors ディレクティブは、より細かい制御で同じ役割を果たします——特定の信頼できるオリジンを列挙でき、CSPをサポートするブラウザでは X-Frame-Options を置き換えます。

なぜ重要か

意味のある操作を伴うページ——アカウント設定、支払い確認、メール設定、管理者向けの切り替え——はすべてclickjackingの標的です。悪意あるページにたどり着いたログイン中のユーザーは、何も異常がないように見えるまま、意図しない本物の操作をさせられてしまう可能性があります。

X-Frame-Options の追加にコストはかからず、最新のすべてのブラウザがサポートしています。機密性の高い操作を行うページでこれを省くのは、機能不足ではなく、単純な設定ミスです。

直し方

Next.jsで X-Frame-Options を全体に追加する

next.config.js でヘッダーを設定し、すべてのルートに適用されるようにします。埋め込みを必要としないアプリには、DENY が安全な既定値です。

// next.config.js
module.exports = {
  async headers() {
    return [
      {
        source: "/:path*",
        headers: [{ key: "X-Frame-Options", value: "DENY" }],
      },
    ];
  },
};
CSPに frame-ancestors を追加する

CSPの frame-ancestors ディレクティブは、最新のブラウザで X-Frame-Options を置き換え、オリジン単位の制御を可能にします。すでに設定しているContent-Security-Policyヘッダーに追加してください。

// extend your existing CSP string
const csp = [
  // ... your other directives ...
  "frame-ancestors 'none'",
].join("; ");
自分のドメイン内で埋め込む場合は SAMEORIGIN を使う

自分のサイト内で正当にページを埋め込む場合——同一オリジンのプレビューiframeや埋め込みウィジェットなど——は、DENY の代わりに X-Frame-Options: SAMEORIGIN、または frame-ancestors 'self' を使ってください。

nginxを設定する

nginxのプロキシ経由で応答を配信している場合は、server ブロックにヘッダーを追加してください。

add_header X-Frame-Options "DENY" always;

FAQ

X-Frame-Options と CSP の frame-ancestors、どちらを使うべきですか?

両方使ってください。X-Frame-Options は古いブラウザをカバーし、CSPの frame-ancestors はオリジン単位の細かさを提供する最新の標準です。両者は安全に共存します——CSPをサポートするブラウザは frame-ancestors を使い、X-Frame-Options を無視します。

DENY にすると、自分のウィジェットや分析ダッシュボードの埋め込みが壊れますか?

はい。DENY は自分のオリジンを含め、すべてのフレーム化をブロックします。自分のドメインで特定のページをiframeに埋め込む必要がある場合は、SAMEORIGIN または frame-ancestors 'self' を使ってください。緩めるのは、本当に埋め込みが必要なページだけにしましょう。

X-Frame-Options がない場合、AppSafeはどの深刻度で報告しますか?

中です。それ単体では即座にデータを盗む経路ではありませんが、アカウント操作を行うページは、これがないと実際にclickjackingのリスクがあります。

あなたのアプリは大丈夫ですか?

AppSafeなら、この問題を含む数十項目を1回の無料スキャンでチェックできます。

アプリを無料でスキャン