クロスサイトスクリプティング(XSS):攻撃ベクトルと防御策

Security2026-09-13TryQuickToolBox

XSSが依然としてWebアプリケーションを悩ませる理由

クロスサイトスクリプティング(XSS)は、最も蔓延しているWeb脆弱性の一つであり続けています。広く認知されているにもかかわらず、OWASP Top 10に常に登場します。根本的な問題は、アプリケーションがユーザー入力を信頼し、適切な処理を行わずにレンダリングすることです。攻撃者は悪意のあるスクリプトを注入し、それが被害者のブラウザで実行されることで、セッションハイジャック、データ窃取、改ざんなどが発生します。

この記事では、XSSの攻撃ベクトルを分解し、今日から実装できる実用的な防御策を提供します。

XSSとは何か、どのように機能するのか?

XSSは、アプリケーションが検証やエンコーディングを行わずに信頼できないデータをWebページに含めることで発生します。ブラウザは、注入されたスクリプトを正当なサイトの一部であるかのように実行します。スクリプトは脆弱なサイトのコンテキストで実行されるため、Cookieやローカルストレージにアクセスし、ユーザーに代わってリクエストを行うことができます。

クエリを反映する単純な検索ページを考えてみましょう:

<?php echo 'You searched for: ' . $_GET['q']; ?>

攻撃者が search.php?q=<script>alert('XSS')</script> のようなURLを作成すると、被害者がリンクを訪問したときにスクリプトが実行されます。

XSSの主な3つのタイプ

1. 反射型XSS

悪意のあるスクリプトがリクエスト(例:URLパラメータ)の一部であり、応答に即座に反映されます。被害者はリンクをクリックするかフォームを送信するよう騙される必要があります。これはフィッシングキャンペーンでよく使用されます。

2. 格納型XSS

スクリプトがサーバー上(例:データベース、コメントフィールド、ユーザープロファイル)に永続的に保存されます。影響を受けるページを訪れるすべての訪問者がスクリプトを実行します。格納型XSSは、ページを閲覧する以外の操作を必要としないため、より危険です。

3. DOMベースXSS

脆弱性は、信頼できないソース(location.hashなど)からデータを読み取り、安全に処理せずにDOMに書き込むクライアント側のJavaScriptに存在します。サーバーは悪意のあるペイロードを決して見ないかもしれません。

document.getElementById('output').innerHTML = location.hash.substring(1);

ハッシュに <img src=x> が含まれている場合、スクリプトが実行されます。

一般的な攻撃ベクトル

XSSに対する防御策

1. 出力エンコーディング(コンテキストに応じたエスケープ)

HTML、属性、JavaScript、CSS、またはURLでレンダリングする前に、すべての信頼できないデータをエンコードします。コンテキストに適したエンコーディングを使用します:

最新のフレームワーク(React、Angular、Vue)はデフォルトで自動エスケープしますが、dangerouslySetInnerHTMLや同様のエスケープハッチを使用する場合は注意が必要です。

2. 入力検証とサニタイズ

許可リストを使用してサーバー側で入力を検証します。リッチテキストの場合は、DOMPurifyなどのライブラリを使用してHTMLをサニタイズし、危険なタグや属性を削除します。

const clean = DOMPurify.sanitize(userInput);

クライアント側の検証だけに依存しないでください。

3. コンテンツセキュリティポリシー(CSP)

CSPは強力な多層防御メカニズムです。実行可能なスクリプト、インラインスクリプト、その他のリソースのソースを制限します。厳格なCSPは、注入が発生した場合でもXSSをブロックできます。

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; object-src 'none';

unsafe-inlineとunsafe-evalは避けてください。正当なインラインスクリプトにはnonceまたはハッシュを使用します。

4. 安全なCookie属性

CookieにHttpOnly(JavaScriptアクセスを防止)とSecure(HTTPSのみ)を設定します。これにより、XSSによるセッションハイジャックを軽減できます。

5. 最新のフレームワークを使用し、危険なAPIを避ける

React、Angular、Vueなどのフレームワークは自動的にデータをエスケープします。innerHTMLによる直接的なDOM操作は避けてください。HTMLを挿入する必要がある場合は、まずサニタイズします。

6. 定期的なセキュリティテスト

SAST、DAST、手動ペネトレーションテストを組み込みます。OWASP ZAPなどのツールは、XSS脆弱性の特定に役立ちます。

XSSタイプと主な防御策の比較

XSSタイプ説明主な防御策
反射型リクエスト内のペイロードが応答に反映される出力エンコーディング、入力検証
格納型ペイロードがサーバーに保存され、全ユーザーに配信されるサニタイズ、出力エンコーディング、CSP
DOMベース安全でないDOM APIを介したクライアント側注入安全なDOM API、CSP、evalの回避

ステップバイステップ:XSS防御の実装

  1. すべての入力ポイントを特定する: フォーム、URLパラメータ、ヘッダー、Cookie。
  2. コンテキストに応じた出力エンコーディングを適用する: 組み込み関数またはOWASP Java Encoderなどのライブラリを使用します。
  3. リッチテキストをサニタイズする: DOMPurifyなどを使用します。
  4. CSPを導入する: レポートのみのモードから始め、その後強制します。
  5. HttpOnlyおよびSecure Cookieを設定する。
  6. 開発者を教育する: セキュアコーディング手法についてトレーニングします。
  7. 定期的にテストする: セキュリティテストをCI/CDに統合します。

FAQ

XSSとCSRFの違いは何ですか?

XSSは被害者のブラウザで悪意のあるスクリプトを実行しますが、CSRFはユーザーが認証されているサイトに不正なリクエストを送信するようにブラウザを騙します。XSSはCSRF保護をバイパスするために使用されることがあります。

コンテンツセキュリティポリシーはXSSを完全に防ぐことができますか?

いいえ、CSPは多層防御の手段です。リスクを大幅に軽減しますが、適切な出力エンコーディングと入力検証に代わるものではありません。設定が不適切なCSPでは、一部の攻撃が依然として可能です。

クライアント側の検証だけでXSSを防ぐのに十分ですか?

いいえ。クライアント側の検証は簡単にバイパスできます。常にサーバー側で検証とエンコーディングを行い、すべてのクライアントデータを信頼できないものとして扱ってください。

結論

XSSは持続的な脅威ですが、出力エンコーディング、入力検証、CSP、安全なCookieといった多層防御戦略により、効果的に軽減できます。警戒を怠らず、フレームワークを最新に保ち、継続的にテストしてください。

追加のセキュリティツールについては、サーバーログの不審なパターンを検出するNginx Log Analyzerをご覧ください。