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

玄関の鍵を閉めても「窓」が開いていたら?DOM-based XSSの正体を暴く

皆さん、こんにちは。現場で泥臭いインシデント対応をしていると、「完璧なセキュリティ対策をしたはずなのに、なぜか侵入された」という相談をよく受けます。

多くのエンジニアは、サーバー側のセキュリティには敏感です。玄関に頑丈な鍵(WAFなど)をかけ、防犯カメラ(ログ監視)を設置する。それは素晴らしいことです。しかし、「JavaScriptという名の窓」から、泥棒が直接リビングに入り込んでいることに気づいていないケースがあまりにも多い。

今日は、そんな「窓からの侵入」、すなわちDOM-based XSS(DOMベースのクロスサイトスクリプティング)について、専門用語を抜きにして紐解いていきましょう。

—

1. そもそも「DOM-based XSS」って何?

家で例えてみましょう。あなたの家の玄関(サーバー)には最新の電子ロックが付いています。でも、あなたが「家の外から見えるメッセージボード」に、通りすがりの人が書いたメモをそのまま表示する機能を持たせたとします。

もし、そのメモに「このドアを開けて」という怪しい暗号が書かれていたら? それを読んだ家族が、うっかりドアを解錠してしまう。これがXSSの仕組みです。

DOM-based XSSは、特に「あなたの家(ブラウザ)の中で完結する悪だくみ」です。サーバーを通さず、JavaScriptが勝手にURLのメモを読み取って、勝手に実行してしまう。泥棒はあなたの家の外から、ブラウザという「窓」に向かって悪意あるコードを投げ込むだけでいいのです。

2. 攻撃のメカニズム:ソースとシンクの「危険な出会い」

この脆弱性は、主に2つの要素が出会ったときに発生します。

  • ソース(Source): 泥棒が情報を送り込む場所。例えば、URLの末尾(#以降のフラグメントなど)。
  • シンク(Sink): 危険な実行場所。JavaScriptが受け取った情報を「そのまま動かしてしまう」命令。

悪い例(脆弱なコード)

例えば、URLのフラグメント(#以降)に名前を表示するような機能を作ったとします。

// URLの # の後ろを読み取って、そのまま画面に反映するコード
var name = location.hash.substring(1);
// 「ソース」が location.hash になる

// ページ内の要素にそのまま書き込む
document.getElementById(“welcome”).innerHTML = “ようこそ、” + name + “さん!”;
// 「シンク」が innerHTML 。これが一番の曲者です。

もし、攻撃者がURLを以下のように書き換えて誰かに踏ませたらどうなるでしょう?

https://your-site.com/#

ブラウザは「ああ、これはただの画像表示の失敗だな」と解釈して、勝手にalert(JavaScript)を実行してしまいます。 あなたのサイトの中で、泥棒が自分のプログラムを動かせてしまったのです。

—

3. どうすれば防げるの?「窓」に格子をはめる方法

対策は難しくありません。「外部から来たデータは、たとえ友達からのメモでも一度疑う」という姿勢が重要です。

対策A:HTMLとして解釈させない(innerTextを使う)

innerHTMLは、「ここをHTMLとして読み込んで!」という命令です。これを「ただの文字として表示して!」という命令(innerText や textContent)に変えるだけで、攻撃コードはただの文字列として表示されるだけになります。

// 安全な実装例
var name = location.hash.substring(1);
document.getElementById(“welcome”).textContent = “ようこそ、” + name + “さん!”;
// textContent を使えば、タグは無効化され、安全に表示されます。

対策B:ブラウザにルールを教える(CSP:Content Security Policy)

「万が一、コードが紛れ込んでも実行するな!」とブラウザに強力な命令を出せます。これがCSPヘッダーです。

HTTPレスポンスヘッダーの設定例
Content-Security-Policy: default-src ‘self’; script-src ‘self’;

これは「自分のサイトのプログラム以外は一切動かさない」という強い境界線を引く設定です。もし泥棒がコードを埋め込んでも、ブラウザが「これは許可されていないプログラムだ!」と実行を拒否してくれます。

—

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

DOM-based XSSは、サーバー側でいくら対策しても防げない、ブラウザ(クライアント)特有の落とし穴です。

「URLからデータを取って、画面に出すだけだから簡単だろう」という油断が、泥棒を招き入れます。「データを受け取る場所(ソース)」と「画面に表示する場所(シンク)」が直結していないか? 開発のたびに、この視点を持つだけで、あなたの書くコードの安全性は劇的に向上します。

一歩ずつ、安全な開発を積み重ねていきましょう。あなたのコードが、世界中のユーザーを守る盾になるのですから。

それでは、また次回のセキュリティ・ラボでお会いしましょう!

コメント

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