3秒でわかる
透明にした別サイトの画面を重ね、利用者に見えているボタンとは違うものを押させる攻撃。表示側のヘッダ設定で枠内表示を禁じて防ぎます。
もう少し詳しく
どういうものか
クリックジャッキングは、攻撃者のページに標的サイトを iframe で読み込み、透明にして重ねることで、利用者が見ているボタンとは別のボタンを押させる攻撃です。利用者の目には「無料で診断する」という自作のボタンが映っていますが、実際に指が触れているのは、その上に透明で重なった標的サイトの退会ボタンや連携許可ボタンです。
押した本人はログイン済みなので、操作は正規の手続きとして通ります。サーバー側のログには本人の正しい操作としか残りません。
なぜ必要か
一クリックで完了する操作はどれも標的になります。外部サービスとの連携許可、公開設定の変更、退会、購入の確定、投稿の削除。とくに確認画面が一枚だけの機能は、その一枚を透明にして踏ませれば終わりです。入力を伴わないため、パスワードを盗まれていなくても被害が出ます。
具体例
攻撃側は重ねるだけで作れます。
<style>
#bait { position: absolute; top: 120px; left: 40px; z-index: 1; }
iframe { <a href="/glossary/position" class="text-primary font-medium underline underline-offset-2 hover:text-primary-dark">position</a>: absolute; top: 0; left: 0; width: 600px; height: 400px;
opacity: 0; z-index: 2; }
</style>
<button id="bait">無料で診断する</button>
<iframe src="https://example.com/settings"></iframe>防ぐのは表示される側の役目で、応答ヘッダで枠内表示を制限します。
Content-Security-Policy: frame-ancestors 'self'
X-Frame-Options: SAMEORIGINExpress なら helmet を入れるだけで、この二つが既定で付きます。
つまずきやすいところ
自分のサイトが被害を受けるのに、直せる場所は自分のサイトの応答ヘッダである、という関係を掴み損ねると対策が進みません。攻撃者のページには手を出せないので、枠に入れられること自体を拒否します。
古い X-Frame-Options だけを頼るのも不十分です。特定のサイトからの埋め込みだけを許す指定は、現在のブラウザでは frame-ancestors で書きます。逆に、決済画面など正規に埋め込まれる想定のページで一律に禁止すると、提携先の表示が壊れます。許可する相手を明示する形にします。SameSite 属性を Strict にしたクッキーを併用すると、枠内でセッションが付かなくなるため被害の範囲も狭まります。
覚え方
「見えているものと押しているものが違う」。透明な一枚を重ねられる前提で、自分のページが枠に入ることを許すかどうかを決めます。
