XSS — 入力した文字が、コードとして実行される
掲示板やコメント欄は、ユーザーが書いた文字を、別のユーザーの画面に表示する仕組みです。このとき、入力された文字をそのままHTMLとしてページに埋め込むと、<script> や onerror などの「タグ」がブラウザに命令として解釈・実行されてしまいます。これがXSS(クロスサイト・スクリプティング)です。
下の図1は、わざと脆弱に作ったコメント欄です。攻撃文字列を投稿して、「他のユーザーのブラウザ」で何が起きるかを見てください。最後に、正しい防ぎ方(エスケープ)も同じ画面で試せます。
「文字」のはずが「コード」になってしまう
脆弱版(①)は、保存された文字を "<div>" + コメント + "</div>" のようにそのままHTMLへ連結しています。だから <b> は本当に太字になり、<script> や onerror はJavaScriptとして実行されます。攻撃者はこれを使って、閲覧者のCookie(ログインセッション)を盗んだり、勝手に操作をさせたりできます。怖いのは、被害者は普通にページを見ただけでやられる点です。
根っこの原因はSQLインジェクションと同じ。「ユーザーが入れたデータ」と「ブラウザへの命令(HTML/JS)」が、同じ1本の文字列に混ぜられていることです。境界がタグの記号(< >)だけで決まるので、攻撃者にその記号を持ち込まれると、データのつもりがコードに化けます。
防ぎ方:出力するときにエスケープする
安全版(②)がやっているのがエスケープ(サニタイズ)です。表示する直前に、< を < へ、> を > へ……と特殊な記号をただの文字に変換します。こうするとブラウザは <script> を「タグ」ではなく「そう書かれた文字列」として表示するだけで、絶対に実行しません。図1の②で同じ攻撃を投稿すると、コードがそのまま文字として見えるだけになるのが確かめられます。ポイントは「入力時」ではなく「出力時(表示する瞬間)」にエスケープすることです。
- XSS
- 入力欄からスクリプトを注入し、閲覧者のブラウザ上で実行させる攻撃。Cookie窃取や成りすましに使われる。
- エスケープ
- < > & などの記号を文字実体参照に変換し、HTMLとして解釈されないようにする処理。
- サニタイズ
- 許可するタグだけ残し危険な要素を取り除く処理。リッチ表示が必要な場面で使う。
- CSP
- 実行できるスクリプトの出所を制限する保険。万一の注入の被害を抑える多層防御。
まとめ
XSSは「表示したいデータが、ブラウザへの命令に化ける」攻撃です。原因はデータとコードの混在、対策は出力する瞬間にエスケープして、記号をただの文字に変えること。フレームワークの多くは標準でこれをやってくれますが、innerHTML や「HTMLをそのまま表示」する機能を自分で使うと穴が開きます。「ユーザー入力をHTMLとして信用しない」——これを徹底すれば、大半のXSSは防げます。