現代のウェブ・エコシステムにおいて、DOM(Document Object Model)はインタラクティブでダイナミックなユーザー体験を可能にする上で極めて重要な役割を果たしています。DOMは、ウェブブラウザがウェブページをロードするときに作成するマップまたはブループリントだと考えてください。見出し、段落、ボタン、画像など、あなたが目にするすべての要素は、この階層構造内のノードとして表現されます。開発者はJavaScriptを使用して、このマップを移動したり、要素を変更したり、新しい要素を追加したり、クリックやフォーム送信などのユーザーアクションに応答したりすることができます。例えば、"Show More" ボタンをクリックすると、DOM を変更して隠しテキストを表示するスクリプトが起動するかもしれません。DOMはインタラクティブで常に更新されるため、静的なHTMLコードとユーザーが体験する動的な動作の間のインターフェイスとして機能し、私たちが当たり前だと思っているインタラクティブな機能を駆動します。
しかし、このような双方向性は、クライアント側のコードに特有の脆弱性への扉を開く可能性があります。セキュリティの専門家(侵入テスト担当者であれ、企業資産の防衛を任務とするエンジニアであれ)にとって、DOMの脆弱性を理解することは、攻略のためだけでなく、予防のためにも不可欠である。

セキュリティの文脈におけるDOM
セキュアなコーディングにおいて、DOM内部でデータがどのように流れるかを監視することは極めて重要である。攻撃者が制御するソース、例えばURLパラメータ(ロケーション検索
)、クッキー(ドキュメントクッキー
)、またはリファラー情報(document.referrer
のような安全でないシンクに注入されると、危険な状態になることがある。 インナーHTML
または eval()
.ソースからシンクへの連鎖が、DOMベースの脆弱性を可能にする。
一般的なDOMの脆弱性
脆弱性タイプ | シンクの例 | 説明 | 潜在的な影響 |
---|---|---|---|
DOMベースのXSS | document.write()element.innerHTML | 攻撃者が制御するデータをサニタイズせずにHTMLに注入することで、任意のJavaScriptの実行が可能になります。 | クッキーの盗難、セッションハイジャック、悪意のあるコンテンツの注入。 |
オープン・リダイレクト | ウィンドウの場所 | 不適切なURL処理により、攻撃者はユーザーを悪意のあるサイトにリダイレクトさせる。 | フィッシング攻撃、マルウェアの配布、ブランドの信用毀損。 |
クッキー操作 | ドキュメントクッキー | 攻撃者は、安全でない JavaScript コードによってセッション・クッキーを上書きしたり盗んだりすることができます。 | アカウントの乗っ取り、セッションの乗っ取り、なりすまし。 |
JavaScriptインジェクション | eval() | 攻撃者が提供した文字列をJavaScriptコードとして実行する。 | クライアント側の完全な侵害、データの流出。 |
ドキュメント・ドメインの操作 | ドキュメント.ドメイン | 同一生成元制限を回避するためにドメインを変更する。 | クロスドメインデータ漏えい、権限昇格。 |
WebSocket URLポイズニング | WebSocket() | WebSocket接続に悪意のあるエンドポイントを提供する。 | データストリームの傍受、不正行為。 |
リンク操作 | 要素.src | 攻撃者はリソースリンクを変更し、悪意のあるコードを読み込ませたり、データを盗んだりする。 | マルウェアのインジェクション、トラッキング、フィッシング・ランディングページ。 |
ウェブメッセージの操作 | ポストメッセージ() | ターゲットフレーム/ウィンドウを操作するために細工したメッセージを送信する。 | データ漏洩、クロスオリジン攻撃。 |
Ajaxリクエストヘッダの操作 | setRequestHeader() | 攻撃者はクライアント側のコードでHTTPリクエストヘッダを制御する。 | APIの悪用、CSRFのような悪用。 |
ローカルファイルパスの操作 | FileReader.readAsText() | 適切な制限なしにクライアントサイドJSでローカルファイルを読み込む。 | 機密ローカルデータの漏洩。 |
クライアント側 SQLインジェクション | ExecuteSql() | クライアント側の DB クエリにサニタイズされていないデータを渡す。 | データ盗難、DB操作。 |
HTML5のストレージ操作 | sessionStorage.setItem() / localStorage.setItem() | 悪意のあるペイロードをブラウザのストレージに保存し、後で実行する。 | 永続的なXSS、クライアントデータへの不正アクセス。 |
クライアント側XPathインジェクション | document.evaluate() | XPathクエリへのインジェクションは、攻撃者にXMLデータへのアクセスを与える可能性がある。 | データ漏洩、不正操作 XMLベースのアプリ・ロジック. |
クライアント側のJSONインジェクション | JSON.parse() | 信頼できないソースから改ざんされたJSONを解析すると、任意のオブジェクトインジェクションが可能になる。 | データの上書き、ロジック操作。 |
DOMデータ操作 | 要素.setAttribute() | 信頼できないデータで属性を設定すると、悪意のある動作を引き起こす可能性がある。 | XSS、クリックジャッキング、ロジックバイパス。 |
サービス拒否(DoS) | RegExp() | 大きな正規表現パターンや悪意のある正規表現パターンはブラウザをフリーズさせる。 | アプリケーションのダウンタイム、パフォーマンスの低下。 |
DOM脆弱性の発見方法
セキュリティ・チームは通常、複数の戦略を組み合わせている。
- アクティブスキャンBurp SuiteやOWASP ZAPのようなツールを使うことで、テスターは安全でないDOMインタラクションをシミュレートし、観察することができる。
- パッシブ・ディスカバリー は、DOMレイヤーに隠された機密データを発見するために、Shodan、ZoomEye、PublicWWW、あるいはWayback Machineの過去のスナップショットのようなリソースを探し回る。
- 自動化された正規表現とAI分析、 は、既知のクレデンシャルのパターンマッチングと、ソース→シンクのフローをマッピングするAI主導の分析を組み合わせることで、検知から修復までの時間を劇的に短縮します。
DOM脆弱性に対する防御
強力な防御は、信頼できるデータだけがDOMに届くように、規律正しい入力検証(理想的にはホワイトリストを通して)から始まる。
エンコード戦略は、文脈に合わせて調整する必要がある:ページ出力のためのHTMLエンコーディング、スクリプト注入ポイントのためのJavaScriptエスケープ、リンク構築のためのURLエンコーディング。
APIキーがどうしてもフロントエンドのコードに表示されなければならない場合は、リファラーやオリジンチェック、IP制限、レート制限を使ってロックする必要がある。
チームは、デプロイ直前にDOMレビューを実施し、シークレットや安全でないコードを削除し、アーカイブされたスナップショットであっても、これまでに公開されたことのある認証情報を取り消すべきである。

PenligentによるDOMセキュリティの向上
従来、徹底的なDOMセキュリティ監査を実施するには、発見用のNmap、インジェクション・テスト用のBurp Suite、悪用用のSQLmapなど、多数のツールをつなぎ合わせ、発見された各事項が正確かどうかを手作業で確認する必要があった。
Penligentは、テスターが目的を分かりやすく説明できるようにすることで、この状況を変える。このウェブサイトをスキャンして DOM 脆弱性を調べろ」というようなリクエストは、インテリジェントなワークフローをトリガーします、 SQLマップなどを使用して、潜在的なソース→シンク・チェーンのターゲット・スキャンを実施し、各検出結果を検証して誤検出を排除し、重大度別にランク付けします。熟練したセキュリティ専門家にとっても、新参者にとっても、DOM監査は、数日に及ぶ手作業のマラソンから、数時間、あるいは数分で完了する合理化された高精度のプロセスへと変貌します。