「そのHTML、本当に安全?」JavaScriptのDOM操作で泥棒を招かないための心得
こんにちは!現場でセキュリティの最前線に立っていると、「便利な道具ほど、扱いを間違えると凶器になる」という場面に何度も遭遇します。
今日は、フロントエンド開発の現場で毎日のように使う「DOM操作」について、少しだけ立ち止まって考えてみましょう。JavaScriptで画面に文字を表示させるとき、皆さんはinnerHTMLとtextContent、どちらを迷わず選んでいますか?
「どっちでも動くなら、HTMLが書けるinnerHTMLの方が便利じゃない?」
そう思ったあなた。実はその選択が、あなたのサイトに「勝手口の鍵をかけ忘れて泥棒を招き入れる」ような隙を作っている可能性があるんです。一緒に紐解いていきましょう!
—
1. 泥棒(攻撃者)は「あなたの家」をどう狙っているのか?
まずは、インジェクション攻撃の仕組みを、身近な「防犯」に例えてみましょう。
あなたのサイトが「家」だとします。ユーザーからの入力(検索窓やコメント欄など)は、「訪問者が届けてくれる手紙」のようなもの。もし、訪問者が悪意のある泥棒だったらどうでしょう?
「ただの挨拶文」を送るフリをして、手紙の中に「この家の中にある全ての宝物(Cookieやユーザー情報)を、俺の指定した場所に送れ」という命令文を仕込んできたら……。
もし、あなたがその手紙の中身を疑わずに「家の壁に貼り付けて(HTMLとして表示して)」しまったら、家中にその命令が響き渡り、泥棒のやりたい放題になってしまいます。これが、Webセキュリティの世界で言う「クロスサイトスクリプティング(XSS)」という攻撃の正体です。
2. innerHTMLという「諸刃の剣」
innerHTMLは、ブラウザに対して「この文字列をただの文字としてではなく、HTMLの一部として解釈して実行してくれ!」と指示を出すプロパティです。
例えば、ユーザー名を表示する際にこんなコードを書いたとします。
// 危険な例:ユーザーが入力した名前をそのままHTMLとして挿入
const userName = ““;
document.getElementById(‘display’).innerHTML = “こんにちは、” + userName;
innerHTMLは、この怪しい文字列の中にあるタグやonerror(エラーが起きたら実行せよという命令)を、「おっ、これは画面を描画するための指示だな!」と真に受けて実行してしまいます。これが攻撃者の狙う「盲点」です。
3. 「文字として扱う」という最強の防御:textContent
一方、textContentは非常に真面目な性格です。これを使うと、ブラウザは「ここに書いてあるものは、どんなにHTMLっぽいタグが含まれていても、絶対にただの文字として表示するぞ」と決めてかかります。
先ほどのコードをtextContentに書き換えてみましょう。
// 安全な例:どんな文字列が来ても「ただの文字」として処理される
const userName = ““;
document.getElementById(‘display’).textContent = “こんにちは、” + userName;
これなら、画面には「こんにちは、」という文字列がそのまま表示されるだけです。ブラウザは「タグ」としての解釈を放棄するので、攻撃者の命令は決して実行されません。
「プログラムにHTMLタグを解釈させないこと」。これが、XSSを防ぐための最もシンプルで強力な防犯対策なのです。
4. 今日からできる「使い分け」のルール
実務で迷ったときは、このルールを思い出してください。
- 基本は
textContentを使う: ユーザーから受け取ったデータや、外部から取得したテキストを表示するときは、必ずこちらを選びましょう。これが「デフォルトの鍵」です。 innerHTMLは「信頼できる場所」だけに: 自分で書いたHTMLを動的に生成する際など、完全に制御できる領域でのみ使用しましょう。- どうしてもHTMLが必要なときは: ライブラリ(DOMPurifyなど)を使って、文字列の中から「悪さをする成分」を事前に取り除く(サニタイズする)という一手間を必ず加えてください。
—
最後に:セキュリティは「疑う」ことから始まる
「動けばいい」という考え方は、開発のスピード感としては素晴らしいものです。でも、プロフェッショナルを目指すなら、そのコードが「どう悪用される可能性があるか」を想像する視点を持つだけで、あなたの作るアプリケーションの品質は劇的に向上します。
セキュリティ対策は、特別な魔法ではありません。今日お伝えしたtextContentへの切り替えのように、一つひとつの小さな「鍵かけ」の積み重ねが、あなたとユーザーを守る大きな壁になるんです。
一歩ずつ、着実に学んでいきましょう!何か不明な点や、さらに深い話が聞きたいことがあれば、いつでも質問してくださいね。皆さんの開発ライフが、安全でクリエイティブなものになりますように!
コメント