前回:やられアプリ BadTodo - 13.1 クリックジャッキング - demandosigno
クリックジャッキング対策はアプリケーションのバグが原因ではなく、HTMLの仕様を巧妙に悪用した攻撃と言えます。このため、バグを修正したら防げるというタイプの脆弱性ではありません。
クリックジャッキング対策はアプリケーション単体では困難なためブラウザ側の支援が必要となります。
『安全なWebアプリケーションの作り方 第2版 p.202』
対策
X-Frame-Optionsに対応したブラウザにおいて下記のようにヘッダを設定する。
- X-Frame-Options: DENY
iframeに入ることを一切拒否。DENYを指定したレスポンスはframeなどの内側で表示されなくなる。 - X-Frame-Options: SAMEORIGIN
同一オリジンに限りiframeに入ることを許可。 - X-Frame-Options: ALLOW-FROM
指定したオリジンのウェブページのみフレーム内の表示を許可。
PHPによりX-Frame-OptionsのSAMEORIGINを指定するには以下のように記述する。
- header('X-Frame-Options: SAMEORIGIN');
一般的には Apacheや nginxの設定で常時このヘッダを出力するとよいです。
Apache で X-Frame-Options を DENY に設定するには、サイトの設定に以下の記述を追加してください(mod_headersが導入されている必要があります)。
- Header always set X-Frame-Options "SAMEORIGIN"
Apache で X-Frame-Options を DENY に設定するには、サイトの設定に以下の記述を追加してください。
- Header set X-Frame-Options "DENY"
nginx で X-Frame-Options ヘッダーを送信するように設定するには、以下の記述を http、server、 location のいずれかの設定に追加してください。
- add_header X-Frame-Options SAMEORIGIN always;
安全なウェブサイトの作り方 - 1.9 クリックジャッキング | 情報セキュリティ | IPA 独立行政法人 情報処理推進機構
BadTodoで試す
common.php の先頭に一行追記。
<?php header('X-Frame-Options: DENY'); define('SESSIDNAME', 'TODOSESSID');
BadTodoにアクセスするとレスポンスヘッダに X-Frame-Options が追加されている。
HTTP/1.1 200 OK Server: nginx/1.23.2 ~中略~ X-Frame-Options: DENY
罠サイトで確認すると、iframe内の表示が拒否されておりクリックできないため罠は失敗します。(表側を少し透明にして確認)

保険的対策:CSRFの際と同様に「重要な処理」の実行後に登録済みメールアドレスに通知メールを送信する。
クリックジャッキングは X-Frame-Optionsヘッダで容易に対策できるため怠らずに対策しておきましょう。
実行ファイルに記述する方法は記述漏れが発生しやすいためお勧めしません。X-Frame-Optionsを指定すべきページは「重要な処理の一つ手前」のページですが、すべてのページでX-Frame-Optionsヘッダを出力しても問題はないためサーバー側の設定で出力した方が良いでしょう。
後日:サーバー側の設定でも試してみる。