「URLの先にある罠」を防げ! DOMベースXSSの仕組みと泥棒を入れないための防犯術
こんにちは!セキュリティの世界へようこそ。
日々コードを書いていると、「サーバーを通さないから安全」なんて思い込んでしまうことはありませんか?実は、それこそが攻撃者にとっての「一番の狙い目」なんです。
今日は、最近のモダンなWebアプリケーションで特に注意が必要な「DOMベースXSS(クロスサイトスクリプティング)」について、家を例えにしながら、どうやって身を守ればいいのかを一緒に紐解いていきましょう。
—
1. DOMベースXSSって、結局どんな「泥棒」なの?
一般的なXSSは、サーバーから送られてくるHTMLに攻撃者が罠を仕掛けます。しかし、DOMベースXSSは一味違います。サーバーは一切汚染されていません。
これを「家の防犯」で例えてみましょう。
- サーバーサイドXSS:泥棒が家の「表札(HTML)」を書き換えて、偽の家族を招き入れるようなもの。
- DOMベースXSS:家主(あなた)が、玄関のポストに届いた「怪しいメモ(URLのフラグメント)」を、ろくに確認もせずリビング(画面)にそのまま貼り付けてしまうようなものです。
URLの後ろにつく #(フラグメント)などは、サーバーには送られません。ブラウザ上のJavaScriptだけが勝手に読み取って表示に使います。この「サーバーが感知しない隙間」を突いて、攻撃者はあなたのブラウザの中で勝手にスクリプトを動かそうとします。
—
2. なぜ「innerHTML」が危険なのか?
開発者の皆さんがよく使う innerHTML。これは「指定した場所に、HTMLを流し込む」という便利な道具ですが、セキュリティの観点からは「壁に穴を開けて、そこから誰でも部屋に入れる状態」と同じくらい危険です。
悪い例:泥棒を招き入れるコード
// URLの # 以降を読み取って、そのまま画面に表示するコード
const params = new URLSearchParams(window.location.hash.substring(1));
const name = params.get(“name”);
// 危険!innerHTMLは「タグ」もそのまま実行してしまいます
document.getElementById(“welcome-message”).innerHTML = “こんにちは、” + name + “さん!”;
もし攻撃者がこんなURLを送ってきたらどうなるでしょう?
https://example.com/#name=
innerHTML は「これはただの文字だ」と判断せず、中のスクリプトを「実行すべき指示」として受け取ってしまいます。結果、画面が表示された瞬間に攻撃者の意図したコードが動いてしまうのです。
—
3. 「鍵」と「防犯カメラ」で対策しよう
では、どうやって防げばいいのでしょうか?対策は大きく分けて2つあります。
① 「innerHTML」を使わない(一番の解決策)
「危険な道具」を使わないのが一番の防犯です。文字を表示したいだけなら、textContent を使いましょう。これなら、たとえ攻撃者がタグを送り込んでも、ブラウザはそれを「ただの文字」として表示するだけで、スクリプトは実行されません。
安全なコード:
// textContentなら、タグが含まれていても「ただの文字列」として扱うので安全です!
const name = params.get(“name”);
document.getElementById(“welcome-message”).textContent = “こんにちは、” + name + “さん!”;
② 「Content Security Policy (CSP)」で玄関を固める
万が一、コードに書き間違いがあった時のための「最後の砦」が CSP(コンテンツセキュリティポリシー) です。これは、Webサイトに対して「どんなスクリプトの実行を許可するか」を定義する、強固な門番のようなもの。
HTTPレスポンスヘッダーに以下のように設定します。
信頼できるソース以外からのスクリプト実行を禁止する設定例
Content-Security-Policy: default-src ‘self’; script-src ‘self’;
これを入れておけば、万が一攻撃者が外部からスクリプトを読み込ませようとしても、ブラウザが「お前は許可リストに載っていない!」とブロックしてくれます。
—
最後に:セキュリティは「疑う」ことから始まる
DOMベースXSSの恐ろしさは、「自分の書いたJavaScriptが、自分を攻撃する武器になる」という点です。
「URLから取得したデータ」は、常に「どこかの誰かが書き換えた可能性がある毒物」だと思ってください。
1. 外部からの入力は、絶対にそのままHTMLに流し込まない!
2. innerHTML よりも、安全な textContent を使う!
3. CSPという門番を立てて、二重のガードをかける!
これだけ意識するだけでも、あなたの作るWebサイトの安全性は劇的に向上します。最初は難しく感じるかもしれませんが、一つずつ「泥棒の侵入経路」を塞いでいく作業は、まるでパズルを解くようで面白いものですよ。
今日からあなたのコードを少しだけ疑って、より強固なアプリケーションを作っていきましょう!応援しています。
コメント