何が起きるか
DOMベースXSSは、ページ内のJavaScriptが、攻撃者の指定したURLなどの値をHTMLやコードとして解釈させ、閲覧者のブラウザで攻撃者のJavaScriptを実行してしまう問題です。
説明用に、URLの検索語を表示用要素のinnerHTMLへ代入するページを考えます。攻撃者がタグとイベント属性を検索語に含むURLを被害者へ開かせると、ページのJavaScriptがその文字列を読み出してinnerHTMLへ渡します。ブラウザは値をHTMLとして解析し、イベント属性が含まれていれば、そのイベントでコードを動かします。値を読む処理とHTMLへの変換が、ブラウザ内にある点がDOMベースの分類です。 無害な説明例として、URLから取り出した検索語が<img src="missing-example" onerror="console.log(1)">なら、innerHTMLはimg要素を作ります。画像が存在せず読み込みエラーが起きると、onerror属性に書いたconsole.log(1)が実行され、コンソールに1を出力します。実際の攻撃では、この処理を情報の読み取りなどへ置き換えます。
実行したコードがページの要素を表すDOMから、ログイン利用者に表示されている非公開メッセージ本文を読み、攻撃者のサーバーへ送れる構成なら、その情報が攻撃者の手元へ届きます。情報を読めることと外部へ送れることは別の条件です。サーバーの元のHTMLに攻撃文字列がなくても、ブラウザがURLから読み込む経路で成立します。
正常ならどう動くか
URLの検索語を表示する機能なら、ページのJavaScriptが検索語を読み、表示用要素のtextContentへ文字列を代入します。検索語に山括弧が含まれていても文字として表示され、HTML要素やイベント処理には変わらないことが期待されます。
不備と攻撃が成立する流れ
攻撃者が、HTMLのタグやイベント属性を検索パラメータに含むURLを作り、被害者に開かせます。ページ内のJavaScriptがその値を表示用要素のinnerHTMLへ渡すと、ブラウザは値をHTMLとして解析します。画像の読み込み失敗など、残った実行可能な属性に対応するイベントが起きると、その属性のJavaScriptが動きます。検索語を文字ではなくHTMLとして解析させる箇所が不備です。
別ウィンドウのコードがpostMessageで送った値や、APIが返すコメントも入力元になります。サーバーへ投稿されたコメントをAPIで取得し、表示側のJavaScriptがinnerHTMLへ渡す場合は、保存された攻撃入力がブラウザの描画時に解釈されます。evalへ文字列を渡す別の経路では、ブラウザがその文字列をJavaScriptの式や文として実行することが原因になります。
起こり得る被害と条件
情報取得の例では、実行されたコードが同じページのDOMから非公開情報を読み、攻撃者のサーバーへHTTPリクエストで送ります。その情報が外部へ届く条件を満たせば、攻撃者は被害者の画面にある情報を入手できます。
API操作の例では、コードが同じオリジンの設定変更APIへHTTPリクエストを送ります。ブラウザがそのリクエストのCookieヘッダーに被害者のログイン用Cookieを付け、APIが変更を許可すれば、被害者の登録メールアドレスなどが攻撃者の指定値へ変わるおそれがあります。
表示偽装の例では、コードがDOMを書き換えて偽の再ログイン入力欄を表示します。被害者が入力したパスワードをコードが読み、攻撃者のサーバーへ送信できれば、攻撃者はその入力値を入手します。どの例も、入力が危険な解釈処理へ届いてコードが実行されることに加え、対象の情報・API・通信が利用できることが条件です。
防ぎ方と、防げる理由
検索語やコメントを文字として表示する場合は、表示用要素のtextContentへ渡し、innerHTMLやevalなどの再解釈を避けます。装飾用HTMLが必要なら、保守されたサニタイザで許可しない要素・属性を除去してから表示します。その後で未検査の文字列を連結すると実行可能なHTMLを再び作るため、表示までの加工全体を確認します。
説明用の擬似コード(実際の製品コードではありません)
// 危険
result.innerHTML = query;
// 修正: テキスト検索語の表示
result.textContent = query;よくある誤解
サーバーの返すHTMLに入力がなくても、ブラウザがURLから取り込めば発生します。また、保存済みコメントをinnerHTMLへ渡す例は格納型でもDOMベースでもあります。保存経路とブラウザ内の原因は別の分類です。
実装の確認点
location、postMessage、API応答のどの値を誰が操作できるか確認し、その値がinnerHTML、outerHTML、insertAdjacentHTML、evalへ届くまで追います。サーバーの元のHTMLだけでは、ブラウザ内で追加された値を確認できません。実行後のDOMと、値を受け渡すJavaScriptを合わせて調べます。
出典・確認範囲
- [1] Web Security Academy: DOMベースXSSPortSwigger / 確認日 2026-11-01