XSSとは?CSRFとの違いを詳しく比較

Webアプリの脆弱性としてよくセットで語られるのが「XSS」と「CSRF」です。
名前が似ていて混同されがちですが、狙いも成立条件も対策も別物です。この記事では、結論→具体例→対策→チェックリストの順で整理します。
結論:XSSとCSRFの違い(比較表)
- XSS:ユーザーのブラウザ上で 悪意あるスクリプトを実行させる 攻撃
- CSRF:ログイン中ユーザーに 意図しない操作(状態変更)をさせる 攻撃
| 項目 | XSS(クロスサイトスクリプティング) | CSRF(クロスサイトリクエストフォージェリ) |
|---|---|---|
| 狙い | ブラウザで不正なスクリプトを動かす | ログイン中の権限で意図しない操作を実行させる |
| 主な被害 | 画面改ざん、フィッシング誘導、情報漏えい(セッション等)、不正操作の足がかり | パスワード変更、メール変更、送金、投稿/削除などの「状態変更」 |
| 成立条件 | 出力時の扱いミス(エスケープ不足など) | Cookieが自動送信される設計+正当性確認が弱い |
| 入口になりやすい場所 | コメント、検索結果、プロフィール、管理画面の入力など | 外部サイトのリンク/フォーム/画像/JSなどからの誘導 |
| 代表的な対策 | 出力時エスケープ(文脈別)、テンプレート自動エスケープ、CSP | CSRFトークン、SameSite Cookie、Origin/Referer検証(補助) |
| テスト観点 | HTML/属性/JS/URLそれぞれの文脈で無害化できているか | トークン無し・不正Originで状態変更が通らないか |
XSS(クロスサイトスクリプティング)とは
XSSは、アプリが受け取った入力値を適切に無害化せずに表示してしまい、結果として 閲覧者のブラウザ上で不正なスクリプトが動く 脆弱性です。
押さえるべきポイントは次の2つです。
- XSSは「入力が危ない」よりも、出力(表示)の扱いが危ない
- 対策の中心は「入力チェック」ではなく、出力時のエスケープ(文脈別)
CSRF(クロスサイトリクエストフォージェリ)とは
CSRFは、ユーザーがログイン中であることを利用して、攻撃者が用意したページなどから 本人の意思に反して“状態変更リクエスト”を送らせる 攻撃です。
ブラウザは通常、対象サイトへのリクエストにCookieを自動的に付けるため、サーバ側が「この操作は本人の意思か?」を追加で確認しないと成立します。
具体例で理解する:XSSとCSRFの典型パターン

XSSの例
- コメント欄やプロフィールの「自己紹介」など、ユーザー入力が画面に表示される
- 表示にエスケープ漏れがある
- 入力に混ぜたコードが閲覧者のブラウザで動く
→ フィッシング誘導、画面改ざん、情報取得などにつながる
CSRFの例
- ユーザーがあなたのサービスにログイン中
- 攻撃者のサイトを開く
- そのページ内の仕掛けで、あなたのサービスに「メール変更」「パスワード変更」などのリクエストが送られる
- サーバがCSRFトークン等で防いでいないと、ログイン中の正規ユーザー操作として通ることがある
なぜ混同される?どこが決定的に違う?
混同されがちなのは、どちらも「ブラウザ」が絡むからです。ですが本質は違います。
- XSS:ブラウザの中で コードが実行される(表示の安全性の問題)
- CSRF:ブラウザが リクエストを送る(操作の正当性の問題)
補足:XSSがあると、ページ内で正規操作を実行できてしまい、結果としてCSRFより強力な不正操作につながることもあります。
XSSの種類と特徴
反射型XSS(Reflected XSS)
- URLパラメータなどが、その場で画面に反映されるタイプ
- 例:検索ワードをそのまま表示する、エラーメッセージに入力値を混ぜて表示する
- 誘導リンク(フィッシング)と組み合わさりやすい
格納型XSS(Stored XSS)
- 悪意ある入力がDB等に保存され、後から閲覧したユーザーに影響するタイプ
- 例:コメント、掲示板、プロフィール、管理画面のメモ欄など
- 被害が広がりやすく、優先度高で対策すべき
DOM型XSS
- サーバ側ではなく、ブラウザ側のJavaScript処理(DOM操作)で発生するタイプ
- 例:location.hashやクエリ文字列をJSで取り出して、そのままinnerHTMLに入れる
- 「サーバは安全でもフロントで事故る」ので見落とされやすい
XSS攻撃の対策方法
XSS対策は「入力を消す」よりも、出力する時に適切に無害化するのが基本です。
- 出力時エスケープを徹底する(文脈別に)
- HTML本文に出す
- HTML属性に入れる
- JavaScript文字列として埋め込む
- URLとして埋め込む
- テンプレートの自動エスケープを無効化しない(安易なraw出力を避ける)
- innerHTMLのような危険なDOM操作を避け、textContent等の安全なAPIを使う
- CSP(Content Security Policy)を導入して被害を減らす(保険として有効)
- ライブラリ/フレームワークを最新に保つ(既知の穴を踏まない)
CSRF攻撃の対策方法
CSRF対策は「その操作が本人の意思か」をサーバ側で確認することが中心です。
- 状態変更(POST/PUT/PATCH/DELETE)にCSRFトークンを必須にする
- CookieにSameSite属性を付ける(Lax/Strictを検討)
- Origin/Referer検証を入れる(ただし単独依存は避け、トークンと併用)
- 重要操作は再認証(パスワード再入力、2FA、確認画面)を組み合わせる
- GETで状態変更しない(リンクを踏んだだけで変更が走る設計は危険)
開発会社が注意すべきポイント(チェックリスト)
設計・実装
□ 状態変更は必ずPOST系で行い、CSRFトークンを必須にしている
□ SameSite Cookieの方針が決まっていて、環境差(Safari等)も考慮している
□ 表示する値は原則エスケープされ、raw出力はレビュー対象になっている
□ HTML/属性/JS/URLなど、出力文脈ごとの安全策が理解されている
□ innerHTMLの使用箇所が棚卸しされ、安全な代替に置き換えられている
テスト・運用
□ 「トークン無し」で状態変更が通らないことをテストしている
□ 主要な入力・表示ポイント(コメント、検索、管理画面等)でXSS観点のテストをしている
□ セキュリティヘッダ(CSPなど)の導入状況を定期点検している
□ 依存ライブラリの更新ルールがある(脆弱性アラートを見ている)
よくある質問(FAQ)
Q. 入力値検証(サニタイゼーション)だけでXSSは防げますか?
完全には防げません。入力側での制限は補助にはなりますが、基本は出力時エスケープです。表示の文脈ごとに正しく無害化する必要があります。
Q. CSRFトークンがあればSameSiteは不要ですか?
基本はトークンが主役ですが、SameSiteは被害を減らすのに役立つため併用が推奨です(ただし互換性や要件に合わせて設計)。
まとめ
- XSS:ブラウザで不正スクリプトが動く(表示の安全性)→ 対策は出力時エスケープが中心
- CSRF:ログイン中ユーザーに不正操作をさせる(操作の正当性)→ 対策はCSRFトークンが中心
- 比較表→具体例→対策→チェックリストの順で押さえると、開発現場でそのまま使えます
