XSS
Cross-Site Scripting
Webページの処理の不備によって、攻撃者のスクリプトが閲覧者のブラウザ上で、そのサイトの権限で実行される脆弱性や攻撃です。画面の書き換えや、利用者に代わる操作などにつながります。
🐾 猫で例えると?
特等席にいた茶トラの隙間へアメショが割り込む姿を、画面の正規の内容へ別のものが入り込む例えにします。XSSで重要なのは窮屈さや処理の重さではなく、「表示するだけのデータ」が「実行する命令」として扱われることです。
💻 セキュリティにおける「XSS」とは?
XSSは、信頼できない値をHTMLやスクリプト等の実行につながる場所へ安全でない方法で渡すと起こり得ます。サーバーの出力だけでなく、ブラウザ内でURLなどを読み、ページの要素をプログラムから扱う仕組みであるDOMを書き換える処理も確認します。
実行されたコードは、そのページで利用者ができる操作を悪用する場合があります。HttpOnlyのCookieはJavaScriptから読めませんが、Cookieを読めなくても認証済みの要求を送ったり、入力を盗み見たりする危険は残ります。
⚠️ XSSの仕組みと種類
XSSは、その攻撃コードがどこを経由してどのように実行されるかによって、大きく3つのタイプに分類されます。それぞれの特性に合わせた多層防御が必要です。
XSSの3大分類
格納型は保存された内容が表示時に実行されるもの、反射型は要求に含まれた値が応答へ返されて実行されるものです。DOM-basedはブラウザ側のDOM操作に原因がある分類で、格納・反射という区分と重なる場合もあります。影響の大きさは分類だけでは決まりません。
// id="output"の要素があるページで、文字列として表示する例
const userInput = "<b>猫の名前</b>";
const output = document.getElementById("output");
if (output) {
output.textContent = userInput; // タグとして解釈せず、そのまま表示
}
// innerHTMLはHTMLを解釈するため、未検証の値を渡さない innerHTMLへscript要素を入れた場合、そのscriptがそのまま実行されるとは限りません。しかし、イベント属性など別の経路でスクリプトが動き得るため安全とはいえません。普通の文字表示にはtextContentを使い、HTMLを許可する必要がある場合は用途に合うサニタイザーを使い、許可しないタグや属性を取り除く処理(サニタイズ)を行います。
🛠️ XSS脆弱性を作り込まないためのポイント
対策は、値を入れる場所に合わせて選びます。記号を命令ではなく文字として扱わせる処理をエスケープと呼びますが、HTML本文向けの処理をURLやJavaScriptの中にもそのまま使えるとは限りません。
- 出力先に合う処理: 通常はテンプレートの自動エスケープを活用し、安全でないHTML挿入を避けます。HTMLを許す場面では、許可する要素や属性を定めたサニタイズを行います。
- CSPを追加の防御にする: CSPは、ページが読み込み・実行を許す内容をブラウザへ伝える規則です。実行を許す目印(nonce)や内容の照合値(hash)を使う方法がありますが、出力処理の修正の代わりにはなりません。
- Cookieを保護する: HttpOnlyやSecure等を用途に応じて設定します。HttpOnlyだけではXSSの発生や本人権限での操作を防げないことに注意します。
猫たちの席の境界を分けるように、プログラムでも「データ」と「命令」の境界を守りましょう。文字を表示するだけならHTMLに変換しない、という小さな選択が防御の基本になります。