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.config.js でヘッダーを設定し、すべてのルートに適用されるようにします。埋め込みを必要としないアプリには、DENY が安全な既定値です。
// next.config.js
module.exports = {
async headers() {
return [
{
source: "/:path*",
headers: [{ key: "X-Frame-Options", value: "DENY" }],
},
];
},
};CSPの frame-ancestors ディレクティブは、最新のブラウザで X-Frame-Options を置き換え、オリジン単位の制御を可能にします。すでに設定しているContent-Security-Policyヘッダーに追加してください。
// extend your existing CSP string
const csp = [
// ... your other directives ...
"frame-ancestors 'none'",
].join("; ");自分のサイト内で正当にページを埋め込む場合——同一オリジンのプレビューiframeや埋め込みウィジェットなど——は、DENY の代わりに X-Frame-Options: SAMEORIGIN、または frame-ancestors 'self' を使ってください。
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のリスクがあります。