1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【セキュリティ】 DOMベースXSSとは?仕組みから対策まで解説

1
Last updated at Posted at 2025-12-20

はじめに

セキュリティアドバイザリを見ると、反射型や蓄積型のXSS(クロスサイトスクリプティング)は今でも頻繁に報告されています。しかし、DOMベースXSSに関しては、近年その報告数が減少傾向にあります。

これはDOMベースXSSがブラウザ内のみで完結し、サーバーとの通信を必要としないという特殊な性質を持っているためです。かつては静的なHTMLページでも簡単に実証できましたが、現代のブラウザはセキュリティが強化されており、攻撃の成立は非常に難しくなっています。

エンジニアが知っておくべき基礎知識を分かりやすく解説します。


1. DOMベースXSSとは何か?

DOMベースXSSとは、ブラウザ上で動作するJavaScriptが、ユーザー入力などの「信頼できないデータ」を安全ではない方法で処理し、DOM(Document Object Model)を書き換えることで発生する脆弱性です。

最大の特徴は、「サーバーサイドの処理を経由せず、ブラウザ(クライアントサイド)だけで攻撃が完結する」 という点にあります。

従来のXSSとの決定的な違い

  • 反射型・蓄積型XSS: 攻撃コードが一度サーバーに送られ、サーバーが生成するHTMLに悪意のあるスクリプトが混入します。
  • DOMベースXSS: サーバーは関与しません。URLのフラグメント(#以降)など、サーバーに送信されないデータを使ってブラウザ内で実行されます。

2. 攻撃のメカニズム:「ソース」と「シンク」

DOMベースXSSを理解する上で重要なのが、Source(ソース)Sink(シンク) という考え方です。

  1. Source (入力元): 攻撃者が操作できるJavaScript上のデータ。
    • location.hash(URLの#以降)
    • location.search(URLのパラメータ)
    • document.referrer(遷移元のURL)
  2. Sink (実行先): 渡されたデータを「実行」したり「HTMLとして描画」したりする危険な関数・プロパティ。
    • element.innerHTML
    • eval()
    • document.write()

「ソースから入った悪意あるデータが、無害化されずにシンクへ到達したとき」 に攻撃が成立します。


3. 具体的な攻撃例

脆弱なコードの例

以下は、URLのハッシュから取得した名前を画面に表示するだけの単純なコードです。

// URL: https://example.com/#Alice
const name = decodeURIComponent(window.location.hash.substring(1));
document.getElementById('display').innerHTML = "こんにちは、" + name + "さん";

攻撃シナリオ

攻撃者は、ターゲットに以下のようなURLを踏ませます。

https://example.com/#<img src=x onerror=alert('XSS')>
  1. ユーザーがこのURLにアクセスする。
  2. スクリプトが # 以降の <img> タグを読み込む。
  3. innerHTML によってHTMLとして展開される。
  4. 画像の読み込みエラーが発生し、onerror 属性内の JavaScriptが実行される

これにより、Cookieの盗難や、偽のログイン画面への誘導といった被害が発生します。


4. DOMベースXSSを防ぐ3つの鉄則

① 危険なプロパティ(innerHTML)を使わない

最も効果的な対策は、HTMLとして解析を行わないプロパティを使用することです。

  • × 悪い例: element.innerHTML = input;
  • ○ 良い例: element.textContent = input; または element.innerText = input;

textContent を使えば、入力されたコードはただの「文字列」として表示されるため、スクリプトが動くことはありません。

② JavaScriptライブラリによるサニタイズ

どうしてもHTML構造を維持したまま動的に描画したい場合は、DOMPurify などの実績あるサニタイズライブラリを使用してください。

// 安全にHTMLをクリーンアップ
const cleanHTML = DOMPurify.sanitize(dirtyInput);
element.innerHTML = cleanHTML;

③ 危険な関数を避ける

文字列をそのままJavaScriptとして実行する eval()setTimeout()setInterval() にユーザー入力を渡すことは絶対に避けてください。


まとめ

DOMベースXSSは、サーバーサイドのセキュリティ対策(WAFなど)をすり抜けてしまうため、フロントエンドエンジニアの意識が非常に重要になります。

  • 「ユーザーが操作できる値(Source)」を信用しない。
  • 「HTMLを描画・実行する機能(Sink)」には慎重になる。

この2点を徹底して、安全なJavaScript実装を心がけましょう。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?