「掲示板に投稿しただけなのに、ユーザーのセッション情報が盗まれた」「問い合わせフォームの入力内容が第三者に送信されていた」――Webアプリケーションの現場で、こうした報告が後を絶たない原因の一つがXSS(クロスサイトスクリプティング)です。
XSSはSQLインジェクションと並び、Webアプリケーションにおける代表的な脆弱性として、OWASP(Open Worldwide Application Security Project)の「OWASP Top 10」にも継続して掲載されています。IPA(情報処理推進機構)への届出件数でも、常に上位を占めている攻撃手法です。
この記事では、XSSの仕組み・攻撃パターン・具体的な防御策について、現場で実践できるレベルで解説します。「XSSという言葉は知っているけれど、何をどう防げばいいのか分からない」という方にも理解できるようまとめました。

XSS(クロスサイトスクリプティング)とは?なぜ危険なのか
XSS(Cross-Site Scripting)とは、Webアプリケーションの画面にスクリプト(悪意のあるプログラムコード)を注入し、そのページを閲覧したユーザーのブラウザ上で不正な処理を実行させる攻撃手法です。名前の「Cross-Site」は、攻撃者のスクリプトが正規サイトを「またいで」動作することに由来します。
XSSが危険である理由は主に3つあります。
・ユーザーの信頼を悪用する: 攻撃者のスクリプトは正規サイトのドメイン上で動くため、ブラウザは「信頼できるサイトからのスクリプト」として扱ってしまう
・被害が利用者に及ぶ: サーバー側ではなく、そのページを閲覧した一般ユーザーが被害を受ける。Cookie(セッション情報)の窃取、偽のログインフォームの表示、フィッシングサイトへの誘導などが代表的な被害
・発見が難しい: サーバーのログには正常なリクエストとして記録されることが多く、攻撃が発生していること自体に気づきにくい
SQLインジェクションがデータベースを狙う攻撃であるのに対し、XSSは「Webページを閲覧しているユーザーのブラウザ」を狙う攻撃です。この違いを押さえておくことが防御の第一歩です。
XSS攻撃の仕組み ― 3つのパターンを知る
XSSは攻撃の経路によって大きく3つのタイプに分類されます。防御のために、それぞれの仕組みを把握しておきましょう。
1. 反射型XSS(Reflected XSS)
最も多いパターンです。攻撃者が細工したURLをユーザーにクリックさせると、URLに含まれた不正なスクリプトがWebサーバーの応答にそのまま反映(反射)され、ユーザーのブラウザで実行されます。
たとえば、検索フォームの検索結果ページで「検索キーワード: ○○」と表示する機能があるとします。このとき、検索パラメータにスクリプトを仕込んだURLをメールやSNSで送りつけ、クリックさせることで攻撃が成立します。
2. 格納型XSS(Stored XSS)
掲示板やコメント欄など、ユーザーの投稿内容がデータベースに保存される機能を狙うパターンです。攻撃者が投稿に不正なスクリプトを仕込むと、その投稿を閲覧したすべてのユーザーのブラウザでスクリプトが実行されます。
反射型と比べて被害の規模が大きくなりやすいのが特徴です。攻撃者がURLを送りつける必要がなく、掲示板を見に来た人が自動的に被害を受けるためです。
3. DOM型XSS(DOM-based XSS)
サーバーを経由せず、ブラウザ上のJavaScriptがURLのパラメータやフラグメント(#以降の文字列)を直接HTMLに反映する処理を悪用するパターンです。サーバーのログに痕跡が残らないため、検知がさらに困難です。
近年のSPA(Single Page Application)の普及により、DOM型XSSのリスクは増加傾向にあります。フロントエンド開発者にとっても見過ごせない脅威です。
具体的な防御手順
XSSの防御は「ユーザーからの入力やURLパラメータを、HTMLにそのまま出力しない」ことが大原則です。以下の対策を組み合わせて多層防御を構築しましょう。
1. 出力時のエスケープ処理を徹底する
XSS対策として最も基本かつ効果的な方法です。ユーザーの入力値をHTMLに出力する際、特殊文字(メタ文字)をHTMLエンティティに変換します。
# エスケープ対象の主な文字 # < → < # > → > # & → & # " → " # ' → '
この変換を行うことで、ブラウザはスクリプトとして解釈せず、ただの文字列として表示します。
重要なのは「入力時」ではなく「出力時」にエスケープすることです。同じデータでも、HTMLに出力する場合、JavaScriptの文字列に埋め込む場合、URLのパラメータに含める場合でエスケープの方法が異なるためです。
# PHPでのエスケープ処理例 # htmlspecialchars()を使用(ENT_QUOTESでシングルクォートも変換) # echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8'); # Pythonでのエスケープ処理例 # markupsafeライブラリを使用 # from markupsafe import escape # output = escape(user_input)
2. Content Security Policy(CSP)を設定する
CSP(Content Security Policy)は、ブラウザに対して「このページで実行を許可するスクリプトの提供元」を指定するHTTPヘッダーです。CSPを設定すると、許可されていない場所から読み込まれたスクリプトや、HTMLに直接書かれたインラインスクリプトの実行をブラウザが自動的にブロックします。
# Apache設定でのCSPヘッダー追加例 # .htaccessまたはhttpd.confに記述 Header set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"
CSPはエスケープ漏れがあった場合の「保険」として機能します。ただし、既存のサイトに導入する際は、正規のスクリプト(Google Analytics、広告タグなど)がブロックされないよう慎重に設定してください。まずは「Content-Security-Policy-Report-Only」ヘッダーで報告モードから始めると安全です。
3. HttpOnly属性でCookieを保護する
XSSの典型的な被害は、セッションCookieの窃取によるなりすましです。CookieにHttpOnly属性を付けると、JavaScriptからのCookie読み取りを禁止できます。
# PHPでのCookie設定例 # session.cookie_httponly = 1(php.iniで設定) # session.cookie_secure = 1(HTTPS環境の場合) # session.cookie_samesite = Lax
HttpOnly属性はXSSそのものを防ぐ対策ではありませんが、万が一XSSが成立した場合の被害を大幅に軽減します。Secure属性やSameSite属性と組み合わせることで、Cookieの保護をさらに強化できます。
4. 入力値のバリデーションを行う
ユーザーからの入力が期待する形式かどうかを、サーバー側で厳密にチェックします。
・型・形式の検証: メールアドレスや電話番号など、定まった形式がある入力は正規表現で検証する
・文字種制限: 名前欄にHTMLタグ文字(< >)が含まれていたら拒否する
・長さ制限: 入力値の最大長を設定し、異常に長い値を弾く
バリデーションだけでXSSを完全に防ぐことはできません。エスケープ処理と組み合わせる「追加の防御層」として位置づけてください。
5. テンプレートエンジンの自動エスケープ機能を活用する
最近のWebフレームワークに標準搭載されているテンプレートエンジン(Jinja2、Blade、ERB、Thymeleafなど)は、変数の出力時に自動でHTMLエスケープを行う機能を持っています。
この機能を有効にしておけば、開発者が個別にエスケープ処理を書き忘れるリスクを大幅に減らせます。ただし「自動エスケープを意図的に無効化する」記述(rawフィルタやhtml_safeメソッドなど)を使う箇所には注意が必要です。
中小企業でも今日からできること
「開発チームがいない」「外注で作ったシステムの中身が分からない」という中小企業でも、以下のステップで対策を進められます。
| 対策 | 内容 | コスト |
|---|---|---|
| CMSのアップデート | WordPress等のCMS・プラグインを最新版に更新する。XSSの脆弱性修正パッチが含まれることが多い | 無料 |
| コメント・掲示板の確認 | HTMLタグの投稿が許可されていないか確認する。不要であればプレーンテキストのみに制限する | 無料 |
| HTTPレスポンスヘッダーの確認 | X-Content-Type-Optionsヘッダー(nosniff)が設定されているか確認する | 無料 |
| WAFの導入 | クラウド型WAFなら導入が容易。XSSの典型的なパターンを自動遮断できる | 月額数千円~ |
| 開発会社への確認 | 出力時のエスケープ処理が実装されているか、開発会社・保守担当に確認する | 無料 |
まず取りかかるべきは「CMSのアップデート」と「コメント機能の確認」です。どちらもコストがかからず、すぐに着手できます。
WordPressを使用している場合、プラグインの脆弱性からXSSが発生するケースが多く報告されています。使っていないプラグインを削除し、残っているプラグインは自動更新を有効にしておくことが効果的です。
よくある誤解と注意点
【注意】「入力時にサニタイズすれば安全」は不十分
入力時にHTMLタグを除去(サニタイズ)する方法は、一見効果的に思えます。しかし、データの用途によっては正当なHTMLタグの入力が必要なケースもあり、一律に除去すると機能を損なう場合があります。また、サニタイズ処理を迂回する手法も数多く知られています。繰り返しになりますが、「出力時のエスケープ」が最も確実な対策です。
【注意】「HTTPSなら安全」は誤解
HTTPS(SSL/TLS)は通信経路を暗号化する技術であり、XSSとは防御レイヤーが異なります。HTTPSは通信の盗聴を防ぎますが、Webアプリケーションの出力にスクリプトが混入することは防げません。「HTTPSだからXSS対策は不要」という判断は危険です。
【注意】「自社サイトにフォームがないから関係ない」は思い込み
XSSはフォームだけで発生するわけではありません。URLパラメータ、Cookieの値、HTTPヘッダーの内容をページに表示する処理があれば、XSSの起点になり得ます。また、外部から読み込んでいるJavaScriptライブラリに脆弱性がある場合も、XSSの被害を受ける可能性があります。
本記事のまとめ
XSS(クロスサイトスクリプティング)は、Webページに不正なスクリプトを注入し、閲覧者のブラウザ上で悪意のある処理を実行させる攻撃手法です。反射型・格納型・DOM型の3パターンがあり、いずれもWebアプリケーションの「出力処理の不備」が根本原因です。
防御の基本は「出力時のエスケープ処理」です。これにCSP、HttpOnly Cookie、入力値バリデーション、テンプレートエンジンの活用を組み合わせて多層防御を構築しましょう。
| 脅威 | 対策 | 優先度 |
|---|---|---|
| 不正スクリプトの実行 | 出力時のHTMLエスケープ処理 | 最優先 |
| インラインスクリプトの注入 | Content Security Policy(CSP)の設定 | 最優先 |
| セッションCookieの窃取 | HttpOnly / Secure / SameSite属性の付与 | 高 |
| 不正な入力値の混入 | サーバー側での入力値バリデーション | 高 |
| 既知の攻撃パターン | WAF導入(根本対策の補助として) | 中 |
Webサーバーのセキュリティヘッダー設定やApacheの基本的なセキュリティ強化については、姉妹サイトLinuxMaster.JPで詳しく解説しています。サーバー設定とアプリケーション対策を組み合わせることで、より堅牢なWeb環境を構築できます。
また、クラウド環境でのWAF設定やセキュリティグループの構成については、CloudMasters.TOKYOでクラウド別の具体的な手順を紹介しています。あわせてご確認ください。
自社サイトのXSS対策、万全ですか?
XSSをはじめとするWebアプリケーションの脆弱性は、正しい知識と適切な実装で防御力を大きく高められます。
正しいセキュリティ知識を体系的に身につけたい方へ、メルマガで実践的なセキュリティ対策ノウハウをお届けしています。


コメント