Webページに悪意のスクリプトを埋め込み利用者のブラウザで実行させる攻撃。
クロスサイトスクリプティング(XSS)とは、Webページに 悪意のスクリプト(=ブラウザの中で動く小さなプログラム)を埋め込み、そのページを開いた利用者のブラウザ上で勝手に実行させる攻撃です。スクリプトを実行するのはサーバではなく、ページを見た人の手元のブラウザだという点が特徴です。
身近な例で考えると、掲示板の伝言メモに「これを読んだ人は財布を渡せ」と書いておくようなものです。掲示板(サーバ)がそのメモをそのまま貼り出すと、後から読んだ人(利用者)が指示に従わされてしまいます。困るのはメモを書いた本人ではなく、それを読んだ人です。
上のツールで▶ボタンを押すと、攻撃者の投稿がサーバに保存され、別の利用者のブラウザで実行される流れと、エスケープ処理で攻撃が無害化される様子を確認できます。
XSSが成立するのは、Webアプリが 利用者の入力をそのまま画面に表示してしまうからです。ブラウザは届いた文字列の中に <script> があると「これはページが用意した正規のプログラムだ」と信じて実行します。
ここで例にした蓄積型(ストアド)XSSは、次の順で進みます。
・① 注入:攻撃者がコメント欄に <script>…</script> を投稿する
・② 保存:サーバが中身を検査せずそのままデータベースに記録する
・③ 配信:別の利用者がページを開くと、保存されたスクリプトごと送り返される
・④ 実行:利用者のブラウザがスクリプトを実行し、クッキー窃取やなりすましが起きる
XSSには、罠リンクを踏ませて即座に反射させる反射型などの種類もありますが、「入力をそのまま表示してしまう」という弱点は共通です。上のツールのexecuteステップで、被害者のブラウザでスクリプトが動く瞬間を見てください。
XSSの基本対策はエスケープ処理です。これは 特別な意味を持つ記号を、ただの文字に置き換える処理です。具体的には画面に出力する直前に、HTMLの意味を持つ記号を別の表記に変換します。
・<(小なり)→ <
・>(大なり)→ >
・"(二重引用符)→ "
こうすると、ブラウザは <script> を「プログラムの開始」ではなく「<script> という文字の並び」として画面に表示するだけになります。スクリプトとして動かないので攻撃は失敗します。引用符の中を意味のない文字にしてしまうイメージです。
エスケープに加えて、次の対策も組み合わせると効果的です。
・入力値検証:危険な記号を含む入力をはじく
・クッキーへのHttpOnly付与:スクリプトからクッキーを読めないようにする
・CSP(コンテンツセキュリティポリシー):許可した出所のスクリプトだけを動かす
XSSが成立する根本原因は、ブラウザが「サーバから届いたHTML」を無条件に信頼する仕組みにあります。ブラウザはページを読み込むとき、HTMLの中にある <script> タグを見つけると「このページが用意したプログラムだ」と判断して自動的に実行します。サーバが攻撃者の文字列を検査せずHTMLに含めると、ブラウザはそれを正規のスクリプトと区別できません。
本や雑誌のメタファーで考えると、出版社(サーバ)が読者からの投稿文を校閲せずにそのまま印刷した結果、「この本を読んだら財布を渡せ」という指示が本文に混入したようなものです。読者(ブラウザ)は本に書いてある内容を信用して読みます。エスケープ処理は「校閲作業」にあたり、危険な指示を無害な文字に置き換えます。
つまり、サーバ側でエスケープをしっかり行えば、どんな文字列が投稿されてもブラウザは「ただの文字」として表示するだけになり、スクリプトとして動きません。上のツールのdefenseステップで、同じ文字列でもエスケープ処理によって無害化される様子を確認してください。
| 種類 | スクリプトの保存場所 | 被害の広がり方 |
|---|---|---|
| 蓄積型(ストアド型) | DBに保存される | ページを開く全員が被害を受ける |
| 反射型(リフレクト型) | URLパラメータに含む | 罠リンクを踏んだ人が被害を受ける |
| DOM型 | URLのフラグメント部分 | JavaScriptがURLを直接DOM操作する場合 |
XSSには主に3つの種類があります。このページのツールで示した蓄積型(ストアド型)は、スクリプトがサーバのDBに保存されるため、特定の罠を踏まなくてもページを開いた全員が被害を受けます。被害が広範囲に及ぶため最も危険な種類です。
反射型(リフレクト型)は、スクリプトを含む悪意のURLを踏んだ人だけが被害を受けます。フィッシングメールや偽リンクと組み合わせて使われます。どの種類でも対策の基本は同じです。
・出力時のエスケープ処理:HTMLに埋め込む前に特殊記号を無害化する
・入力時の検証:危険な文字を含む入力をはじく
・HttpOnly属性:クッキーをJavaScriptから読み取れないようにする(クッキー窃取を防ぐ)
・CSP(コンテンツセキュリティポリシー):許可された出所のスクリプトだけを実行する
XSSで最も怖い被害のひとつがクッキーの窃取です。クッキー(=ブラウザがWebサイトごとに保存する小さなデータ)には、ログイン済みであることを証明する情報が入っています。これを盗まれると、攻撃者があなたになりすまして同じサイトにログインできてしまいます。
なぜスクリプトがクッキーを盗めるのか:ブラウザはページ内で動くスクリプト(JavaScript)に対して、そのページに関連するクッキーを読む権限を与えています。埋め込まれたスクリプトが「クッキーの内容を外部のサーバへ送り出す命令」を含んでいると、利用者が気づかないうちにクッキーが流出します。
この被害を防ぐ補助的な対策がHttpOnly属性(=クッキーにつける設定)です。この属性を付けると、JavaScriptからそのクッキーを読み取れなくなります。スクリプトが盗もうとしても「読めない」状態になるため、クッキー窃取は成立しません。根本対策のエスケープ処理と合わせて使うことで多重の防御になります。
XSSが脅かすのは主に機密性(情報を漏らさないこと)です。クッキーや画面上の個人情報が盗まれ、なりすましが起きます。データを直接書き換えたりサービスを止めたりする攻撃ではないので、完全性や可用性は間接的には影響を受けることがあっても、主な標的は機密性です。
他の攻撃と比べるとXSSの特徴が明確になります。
・SQLインジェクション:DBを操作する(機密性+完全性を脅かす)
・XSS:閲覧者のブラウザを操る(機密性=クッキー窃取が主)
・DoS攻撃:サービスを止める(可用性を脅かす)
つまりXSSの被害者は主にサイトの利用者であり、サーバのデータが直接盗まれるわけではありません。しかし利用者のクッキーを奪われると攻撃者がその人になりすましてサイトを使えるため、結果としてサービス全体の信頼が損なわれます。だからこそ、サーバ側でのエスケープ処理とクッキーの適切な設定(HttpOnly)の両方が欠かせません。