「悪意あるスクリプト」を玄関に入れないために。XSSからWebサイトを守るDOM操作の鉄則
こんにちは。セキュリティの世界で泥臭い現場を駆け回っているエンジニアです。
皆さんは「XSS(クロスサイトスクリプティング)」という言葉を聞いたことはありますか?初心者向けのセキュリティガイドを読むと、決まって「恐ろしい攻撃」として紹介されていますよね。でも、いざコードを書くとなると、なぜそれが危険なのかピンとこないことも多いはずです。
今日は、小難しい理論は一旦脇に置いて、「Webサイトの玄関」という身近な例え話で、この攻撃の正体と、今日からできる一番確実な対策についてお話しします。
—
1. 泥棒は「あなたの親切心」を悪用する
想像してみてください。あなたのWebサイトは、大事なお客様(ユーザー)を迎える「お家」です。
XSS攻撃とは、「本来ならただのメッセージを書くはずの場所に、泥棒がこっそり『合鍵を作るための型』を置いていく」ようなものです。
例えば、掲示板や検索結果の画面。ここに悪意ある人が、こんなスクリプトを書き込んだとしましょう。
普通の人は「ただの文字」だと思うでしょう? しかし、ブラウザはこれを「命令」として受け取ってしまいます。
「おっ、スクリプトだ!実行しなきゃ!」と、あなたのサイトを表示した他のお客様のブラウザが、勝手にその命令を実行してしまうんです。結果、お客様のCookie(ログイン情報など)が泥棒の元へ送られてしまいます。これがXSSの恐ろしさです。
—
2. なぜ innerHTML が「危険な鍵」なのか
Web開発をしていると、画面を書き換えるために innerHTML を使いたくなる場面は多いですよね。
// 危険な例:ユーザーの入力をそのままHTMLとして解釈させてしまう
const userComment = ““;
document.getElementById(‘comment-box’).innerHTML = userComment;
innerHTML は、渡された文字列を「HTMLタグ」として解析しようとします。つまり、「玄関のドアに、鍵穴を勝手に増設していいよ」と許可を出しているのと同じなんです。泥棒にとって、これほど都合のいい状況はありません。
安全な代替API: textContent という「透明な壁」
そこで登場するのが textContent です。これを使うと、渡された文字列を「ただの文字」としてしか扱いません。たとえそこに という文字が含まれていても、ブラウザはそれを命令として実行せず、そのまま画面に文字として表示します。
// 安全な例:文字として扱うため、スクリプトはただのテキストになる
const userComment = "";
document.getElementById('comment-box').textContent = userComment;
// 画面には という文字列がそのまま表示されるだけ。実行はされません!
たったこれだけで、泥棒が置いた「型」は無効化されます。innerText も似たような働きをしますが、表示スタイルまで考慮する分、処理が少し重くなることがあります。基本的には textContent を使うのが、モダンな開発の正解です。
---
3. 「防犯カメラ」を設置しよう(セキュリティヘッダー)
コードを直すのと並行して、お家全体に防犯カメラを設置するイメージで「CSP(Content Security Policy)」というヘッダーを設定しましょう。
これは、「このWebサイトでは、許可していない場所からのスクリプトは一切動かさない!」とブラウザに宣言する仕組みです。
HTTPレスポンスヘッダーの設定例
Content-Security-Policy: default-src 'self'; script-src 'self';
- default-src 'self': 基本的に、自分のサイト以外から持ってきたデータは信頼しない。
- script-src 'self': 外部の怪しいスクリプトは一切読み込まない。
こうしておけば、仮にどこかで脆弱性を見逃してしまったとしても、泥棒が外からスクリプトを読み込もうとしてもブラウザがブロックしてくれます。まさに「二重の防犯」ですね。
---
最後に:一歩ずつ、確実に。
「HTMLを動的に書き換えるな」と言っているわけではありません。ただ、「ブラウザに解釈させる入力」と「ただ表示するだけの入力」を厳密に分けることが、セキュリティエンジニアとしての第一歩です。
1. innerHTML は使わない(textContent で代用する)。
2. どうしてもHTMLが必要なら、専用のライブラリ(DOMPurifyなど)を通す。
3. CSPヘッダーで、万が一の時の逃げ道を塞ぐ。
これらを習慣にするだけで、あなたのサイトの安全性は劇的に向上します。最初は面倒に感じるかもしれませんが、一度身につけてしまえば、それは一生使える「最強の鍵」になります。
今日から、一緒にセキュアなコードを書いていきましょう!何か分からないことがあれば、いつでも相談してくださいね。
コメント