「WAFがあるから安心」は大間違い?XSS攻撃の盲点と、泥棒が笑う「鍵の掛け方」の話
こんにちは!セキュリティの最前線で日々「イタチごっこ」をしているエンジニアです。今日は、Web開発を始めたばかりの皆さんが一度は耳にする「XSS(クロスサイトスクリプティング)」と、その防波堤である「WAF(Web Application Firewall)」の本当の姿についてお話しします。
「WAFを入れてるからXSSは大丈夫でしょ?」と思っていませんか?実はそれ、泥棒に対して「頑丈な門扉があるから、窓には鍵をかけなくていいや」と言っているのと同じかもしれません。
—
そもそもXSSって何だろう?
XSSを身近な例で例えてみましょう。あなたの家のポストに、見知らぬ誰かが「この手紙を読んで」と言って、「読むと勝手に玄関の鍵を開けてしまう魔法の呪文」が書かれた手紙を放り込むようなものです。
攻撃者は、あなたのWebサイトの入力フォームに、そんな「悪意ある呪文(JavaScriptコード)」を書き込みます。そして、そのページを見た他のユーザーのブラウザ上で、勝手にその呪文を実行させてしまうのです。
例えば、こんなコードが送られてきたら大変です。
—
WAFは「空港のセキュリティゲート」
WAFは、こうした攻撃を防ぐための「セキュリティゲート」です。ゲートには「怪しい単語リスト(シグネチャ)」があり、 や alert( といった単語が見つかると、「はい、ストップ!」と遮断します。
しかし、攻撃者はこれを知り尽くしています。彼らは、ゲートをすり抜けるために「難読化」という魔法を使います。
攻撃者が使う「検知回避」のテクニック
WAFが「」という単語を禁止しているなら、攻撃者はこう書きます。
- 大文字と小文字を混ぜる:
(これだけで古いWAFはスルーすることがあります) - エンコードする:
%3cscript%3e(URLエンコードという形式に変換し、ブラウザだけが解読できるようにする) - イベントハンドラを使う:
(画像が表示できないというエラーをわざと起こして、その瞬間にプログラムを動かす)
WAFの正規表現(検知ルール)が「」という文字列だけを探していると、こうした工夫を凝らしたペイロードは、いとも簡単にゲートをくぐり抜けてしまいます。
---
現場でできる「本当に強い」守り方
WAFはあくまで「最後の砦」や「補助輪」です。本当に大切なのは、「自分の家の窓とドアにしっかり鍵をかけること(アプリケーション側の実装)」です。
1. 「出すとき」に無害化する(エスケープ処理)
ユーザーから受け取ったデータを画面に表示するときは、ブラウザが「これはただの文字であって、プログラムじゃないよ!」と分かるように変換します。これを「エスケープ」と呼びます。
// 不適切な実装(ブラウザがプログラムとして解釈してしまう)
element.innerHTML = userInput;
// 安全な実装(ブラウザに「ただの文字」として認識させる)
element.textContent = userInput;
2. HTTPレスポンスヘッダーで「ブラウザに指示」を出す
これが非常に強力です。ブラウザに対して「このサイトでは、怪しいプログラムを実行しないでね」とルールを伝えるヘッダーを設定します。
- Content-Security-Policy (CSP):
「信頼できる場所からのプログラム以外は絶対に実行するな!」とブラウザに強力な制限をかけます。
Webサーバーの設定例 (nginx等の設定)
「自分のドメイン以外のスクリプトは読み込むな」という強力なガード
add_header Content-Security-Policy "default-src 'self'; script-src 'self';";
---
今日からできる一歩
「WAFに頼りきらず、自分のコードを見直す」。これがセキュリティの第一歩です。
1. 入力値は信用しない: どんなデータも「悪意があるかもしれない」という前提で扱う。
2. 出力時にエスケープ: 画面に出す直前に、特殊文字を安全な形式に変換する。
3. CSPを導入する: モダンなブラウザの機能を活用して、万が一の攻撃を無効化する。
セキュリティは、一度やって終わりというものではありません。でも、一つずつ理解して対策を積み重ねることで、あなたのサイトは世界で一番安全な場所になります。
「難しそう…」と感じたら、まずは「自分のサイトの表示部分で、ユーザーの入力値をそのまま表示していないかな?」と確認することから始めてみてください。それだけでも、立派なセキュリティエンジニアの第一歩ですよ!
一緒に、安全で楽しいWebの世界を作っていきましょう。
コメント