出力エンコーディング
コンテキスト別エンコーディング(HTML・JS・URL・CSS)によるXSSとその他のインジェクション防止
出力エンコーディングとは、データを出力する際にそのコンテキスト(HTML・JavaScript・URL・CSS等)に応じた適切なエスケープ処理を行い、インジェクション攻撃を防ぐ技術である。XSS(Cross-Site Scripting)はブラウザ上で悪意あるスクリプトを実行させる攻撃であり、Reflected XSS(URLパラメータの即時反射)・Stored XSS(DBに保存されたデータの反射)・DOM-based XSS(JavaScriptがDOMを操作する際に発生)の3種類に分類される。
コンテキスト別エンコーディングが重要なのは、同じ文字列でもHTML本文・HTML属性・JavaScriptコード・URLパラメータ・CSSの中では異なる文法で解釈されるためである。HTML本文では<を<にエスケープするが、JavaScriptコンテキストでは\u003cにエンコードしなければ意味がない。HTMLエスケープのみを行い、JavaScriptコンテキストや属性コンテキストでの危険な文字を見落とすことがXSSの原因となる。ReactやVueなどのモダンフレームワークはデフォルトでHTMLエスケープを行うが、dangerouslySetInnerHTML(React)やv-html(Vue)は生のHTML挿入を強制するため、ユーザー入力を含むデータには使用してはならない。
CSP(Content Security Policy)は、ブラウザが実行・読み込みを許可するリソースのオリジンをHTTPヘッダーで制限するセキュリティ機構であり、エンコーディングミスが存在しても攻撃スクリプトの実行を阻止する多層防御として機能する。Trusted Types APIはDOM-based XSSを防ぐためのブラウザAPIであり、HTML文字列としてDOMに挿入できる値をTrustedType型に限定することで、任意の文字列のHTML挿入をコンパイル時に防止できる。
コードレビューで着目するポイント
- ユーザー入力由来のデータをHTML出力する際に、フレームワークのエスケープ機能が有効になっているか
dangerouslySetInnerHTML/v-html/innerHTMLにユーザー入力が流れていないか- URLパラメータにユーザー入力を含める際に
encodeURIComponent()でエンコードされているか - JavaScriptコンテキストに動的データを埋め込む際にJSONシリアライズ(
JSON.stringify())が使われているか - テンプレートエンジンが自動エスケープを行うモードで使われているか(
raw・safeフィルタが不用意に使われていないか) - CSPヘッダーが設定されており、
unsafe-inlineやunsafe-evalが含まれていないか <script>タグにサーバーサイドで動的な文字列を埋め込む実装がないか
典型的なアンチパターン
innerHTMLへのユーザー入力代入: element.innerHTML = userComment のようにコメント本文をそのままDOMに挿入する実装。<script>alert(1)</script>を含むコメントが投稿されるとStored XSSが発生する。textContentで代替するか、必要な場合はDOMPurifyでサニタイズすること。
テンプレートの自動エスケープ無効化: Jinja2やEJSで特定のフィールドを「HTMLを含むため」として| safe・<%- %>で生出力する実装。ユーザーが入力できるフィールドへの適用は、Stored XSSの直接的な原因となる。表示のためにHTMLを含める場合はDOMPurifyなどのサニタイザを通すこと。
unsafe-inlineを含むCSP: CSPを設定しているが、インラインスクリプトを許可するためにscript-src 'unsafe-inline'を含めている。インラインXSSペイロードの実行を許可してしまい、CSPの効果が大幅に低下する。ノンスベースCSPまたはハッシュベースCSPへの移行が推奨される。
参考リソース
- OWASP XSS Prevention Cheat Sheet — コンテキスト別エンコーディングの包括的ガイド
- DOMPurify (https://github.com/cure53/DOMPurify) — DOM-based XSS防止のためのHTMLサニタイザライブラリ
- MDN: Content Security Policy — CSP設定の詳細なリファレンスドキュメント
- Trusted Types API (https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/trusted-types) — DOM-based XSS防止のためのブラウザAPI
- OWASP Java Encoder — Javaでのコンテキスト別エンコーディングライブラリ
- 1. 📄アーキテクチャスタイル
- 2. 📄ドメインモデリング
- 3. 📄モジュール分割と依存管理
- 4. 📄データモデリング
- 5. 📄API設計
- 6. 📄整合性とトランザクション
- 7. 📄非同期処理(Queue/Event)
- 8. 📄キャッシング
- 9. 📄ユーザーリサーチ
- 10. 📄情報アーキテクチャ
- 11. 📄インタラクションデザイン
- 12. 📄UX原則とヒューリスティクス
- 13. 📄アクセシビリティ(UX観点)
- 14. 📄UXメトリクス
- 15. 📄スケーラビリティ
- 16. 📄可用性とレジリエンス
- 17. 📄オブザーバビリティ
- 18. 📄環境・インフラ設計
- 19. 📄データマイグレーション
- 20. 📄セキュリティ設計原則
- 21. 📄データ保護とマルチテナント
- 22. 📄LLMセキュリティ
- 23. 📄ビジュアルデザイン原則
- 24. 📄デザインシステム
- 25. 📄コンポーネント設計
- 26. 📄スタイリング
- 27. 📄状態管理
- 28. 📄フロントエンドパフォーマンス
- 29. 📄アクセシビリティ(実装観点)
- 30. 📄アニメーションとインタラクション
- 31. 📄設計原則
- 32. 📄デザインパターン(GoF)
- 33. 📄エンタープライズパターン
- 34. 📄クリーンコード
- 35. 📄リファクタリング
- 36. 📄型設計とコントラクト
- 37. 📄関数型プログラミング概念
- 38. 📄エラーハンドリング
- 39. 📄テスト戦略と哲学
- 40. 📄テスト種別(機能テスト)
- 41. 📄テスト種別(UI・ビジュアル)
- 42. 📄テスト種別(契約・境界)
- 43. 📄テスト種別(非機能テスト)
- 44. 📄テストダブル
- 45. 📄テスト設計技法
- 46. 📄並行処理・マルチスレッド
- 47. 📄パフォーマンス最適化
- 48. 📄ドキュメント管理
- 49. 📄バージョン管理と開発プロセス
- 50. 📄脅威モデリング
- 51. 📄通信保護(TLS)
- 52. 📄暗号化・機密情報管理
- 53. 📄認証・セッション管理
- 54. 📄認可・アクセス制御
- 55. 📄入力バリデーション
- 56. 📄インジェクション攻撃
- 57. 📄出力エンコーディング
- 58. 📄エラーハンドリング(セキュリティ観点)
- 59. 📄SSRF(サーバーサイドリクエストフォージェリ)
- 60. 📄依存関係管理
- 61. 📄設計・実装 参考書籍
- 62. 📄セキュリティ参考資料
- 63. 📄正規化(データベース正規化)