メインコンテンツまでスキップ

XSS(Cross-Site Scripting)

Overview

Webアプリケーションのセキュリティ脆弱性の一種であり、悪意のあるスクリプト(主にJavaScript)がWebページ上で実行されてしまう攻撃。
XSS攻撃が成功すると、ユーザー情報の窃取、セッションの乗っ取り、フィッシング詐欺、サイト改ざんなど様々な被害が発生する。

備考

APIモードでCSRF保護をオフにする。
通常、APIサーバーではクライアント側でのレンダリングは行わないため、HTMLやスクリプトを直接出力することは少なく、APIレスポンスは基本的にJSON形式。
そのため、サーバー側でXSS対策が必要なケースは少なく、クライアント側で適切な対処をするのが一般的。

XSSの種類

XSSには主に次の3つの種類がある。

1. Stored XSS(格納型XSS)

悪意のあるスクリプトがサーバーに保存され、他のユーザーがそのスクリプトを含んだページを閲覧した際に実行される攻撃。

例: 掲示板やコメント欄に悪意のあるスクリプトを埋め込み、それを閲覧したユーザーが被害に遭う。 被害例: ユーザーのセッションIDや認証トークンを盗む攻撃。

<!-- コメント欄に以下のようなスクリプトを投稿する -->
<script>
document.cookie = "session=" + document.cookie;
</script>

2. Reflected XSS(反射型XSS)

攻撃者が細工したURLに悪意のあるスクリプトを埋め込み、ユーザーにクリックさせることでスクリプトを実行させる攻撃です。スクリプトは即時実行され、サーバーには保存されません。

例: フォームやURLパラメータの値がそのままHTML出力される場合。 被害例: フィッシングページへのリダイレクトや、悪意のあるサイトに誘導するスクリプトの実行。

<!-- 攻撃者が以下のURLをクリックさせる -->
<http://example.com/search?query=><script>alert('XSS')</script>

3. DOM-based XSS(DOM型XSS)

クライアントサイドで動作するJavaScriptの脆弱性を利用する攻撃。
HTMLのDOM操作中に、外部からの値を適切にサニタイズせずに直接出力することで発生させる。

例: innerHTML などのJavaScriptメソッドで外部の値をそのまま出力した場合。 被害例: 攻撃者がクライアント側で実行するスクリプトを埋め込むことが可能になります。

// DOM操作に外部データをそのまま使ってしまう例
const userInput = new URLSearchParams(window.location.search).get('name');
document.getElementById('greeting').innerHTML = `Hello, ${userInput}`;

XSSの具体的な被害

  1. Cookieの盗難: 認証セッションIDを盗まれることで、不正ログインされる。
  2. CSRF攻撃の補助: ユーザーが意図しないリクエストを送信させる。
  3. フィッシング詐欺: 偽のログイン画面を表示し、パスワードや個人情報を騙し取る。
  4. ブラウザのリダイレクト: 別の悪意あるサイトにリダイレクトさせられる。

XSS攻撃の防御方法

  1. エスケープ処理 (HTML, JavaScript, CSS) HTMLにユーザー入力を出力する場合は、特殊文字をエスケープする必要がある。 例: < → <, > → > サーバーサイドのテンプレートエンジンやフロントエンドフレームワークを活用する。
  2. 入力値のサニタイズ (検証とフィルタリング) 入力時に不要なタグやスクリプトを除去し、データの形式を検証します。 例えば、HTML入力を受け付けない場合は、すべてのHTMLタグを削除する。
  3. コンテンツセキュリティポリシー (CSP) Content-Security-Policy ヘッダーを設定し、実行できるスクリプトの制限をする。 これにより、外部からのスクリプト実行やインラインスクリプトを防げます。 Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc123'
  4. HTTP-only属性付きCookieの使用 CookieにHttpOnly属性を付けることで、JavaScriptから直接アクセスできなくします。 これにより、スクリプトによる認証情報の盗難を防げます。 Set-Cookie: sessionid=abcdefg; HttpOnly; Secure; SameSite=Strict
  5. 信頼できるライブラリの利用 サニタイズ処理を自作せず、信頼できるライブラリを使用することが推奨されます。 例 DOMPurify(クライアントサイド向け) validator.js(Node.jsサーバーサイド向け)