【入門編】DOMベースXSSの発生メカニズムとクライアントサイドのソース・シンク関係 – アプリケーションセキュリティ & 安全な開発防御ガイド

DOMベースXSS:その「便利さ」が招く、ブラウザの中の泥棒にご用心

こんにちは。セキュリティの現場で日々、複雑な攻撃と格闘しているエンジニアです。

今日は、Web開発の現場で「意外と見落とされがちな落とし穴」である「DOMベースXSS(クロスサイトスクリプティング)」についてお話ししましょう。

「XSSってサーバーが攻撃されるやつじゃないの?」と思っているなら要注意。DOMベースXSSは、サーバーを一切経由せず、あなたのブラウザの中で完結してしまう「ステルス型」の脆弱性なんです。

—

1. 例え話で理解する「DOMベースXSS」

まずは、身近な例えで考えてみましょう。

想像してください。あなたは自分の家に住んでいて、玄関(サーバー)にはしっかりとした鍵をかけています。しかし、家の奥にある「メモ書き用のホワイトボード(DOM)」に、誰かが通りすがりに「勝手に伝言を書ける隙間」があったとしたらどうでしょう?

  • 泥棒(攻撃者):あなたの家(ブラウザ)の中に侵入し、ホワイトボードに「この家の金庫の番号は〇〇です」なんて嘘の情報を書いたり、家族を騙すようなメッセージを残したりします。
  • 被害者(あなた):ホワイトボードに書かれた文字を信じてしまい、大切な情報を漏らしてしまいます。

DOMベースXSSは、まさにこれと同じです。Webページが「URLの末尾(住所の一部)」などを確認せずにそのまま画面に表示してしまうと、悪意ある人がそこに「偽の命令」を忍び込ませることができるのです。

—

2. なぜ起こる?「ソース」と「シンク」の関係

専門用語が少し出ますが、怖がる必要はありません。この2つの言葉だけ覚えてください。

  • ソース(Source):外部からやってくる「データ」の入り口。(例:location.hash=URLの#以降の文字列など)
  • シンク(Sink):データをブラウザが「表示・実行」してしまう場所。(例:innerHTML=HTMLとして中身を書き換える命令など)

攻撃者は、「ソース(怪しいデータ)」を「シンク(危険な実行場所)」に橋渡しさせることで、ブラウザ上で勝手なプログラムを動かします。

危険なコードの例

以下は、URLの末尾(#以降)をそのまま画面に表示してしまう、ちょっと危ないコードです。

// URLの # の後ろを取得する(これがソース!)
var userMessage = decodeURIComponent(window.location.hash.substring(1));

// 画面のdiv要素にそのまま放り込む(これがシンク!)
// もし userMessage に “” が入っていたら…?
document.getElementById(‘display-area’).innerHTML = userMessage;

このページに https://example.com/# とアクセスさせると、ブラウザは「画像を表示しようとしたけど失敗した!じゃあエラー処理としてalert(警告)を実行しよう!」と騙されてしまいます。これが攻撃の仕組みです。

—

3. どうやって防ぐ?「二重の防犯対策」

では、どうすればこの「泥棒」を防げるのでしょうか。対策は大きく分けて2つあります。

対策①:危ない「シンク」を使わない(基本の対策)

innerHTML は、渡された文字列を「HTML」として解釈しようとするため、非常に強力で危険です。「ただの文字」として表示したいだけなら、別の方法を使いましょう。

// 修正版:innerHTMLではなく、textContentを使う
// これなら、仮にスクリプトが混じっていても「ただの文字列」として表示されるだけです!
document.getElementById(‘display-area’).textContent = userMessage;

textContent を使えば、ブラウザはそれをプログラムではなく「ただの文章」として扱うため、攻撃は不発に終わります。

対策②:防犯カメラを設置する(CSPの導入)

もしコードに不備があっても、ブラウザに「怪しい命令は無視せよ」と指示するCSP(Content Security Policy)という仕組みが有効です。HTTPレスポンスヘッダーに以下のような設定を追加しましょう。

HTTPヘッダーの例
「信頼できるソース以外からのスクリプト実行は一切禁止!」とブラウザに伝えます
Content-Security-Policy: default-src ‘self’; script-src ‘self’;

これをしておくだけで、仮に攻撃者がコードを埋め込めたとしても、ブラウザが「このスクリプトは許可されていません!」とブロックしてくれます。

—

最後に:セキュリティは「疑うこと」から始まる

DOMベースXSSは、開発者が「便利にデータを扱いたい」と思った瞬間に、その隙を突いてやってきます。

1. 「ユーザーからのデータは、すべて嘘かもしれない」と疑うこと。
2. 「innerHTML」を安易に使わず、より安全な「textContent」を選ぶこと。
3. 「CSP」という強力な防犯カメラを設置しておくこと。

これらを守るだけで、あなたの作るWebサイトは格段に安全になります。最初は難しく感じるかもしれませんが、まずは「URLの情報をそのまま表示していないかな?」とコードを見直すことから始めてみてください。

一歩ずつ、安全な開発者への道を歩んでいきましょう!応援していますよ。

コメント

タイトルとURLをコピーしました