Shikata Ga Nai

Private? There is no such things.

DOMベースXSSのクラシックパターン:jQueryの`$()`セレクターと`hashchange`イベントを悪用する攻撃手法

Hello there, ('ω')ノ

🧠 概要

jQueryはかつて非常に広く利用されていたJavaScriptライブラリであり、その柔軟なセレクター関数$()はDOM操作に頻繁に使用されていました。しかし、この機能は過去に多くのDOMベースXSS(クロスサイトスクリプティング)脆弱性を生む原因にもなっていました。

特に典型的だったのが、location.hash(URLの#以降の部分)をそのまま$()に渡してスクロール処理などに使う実装です。


🚨 脆弱なコード例

$(window).on('hashchange', function() {
    var element = $(location.hash);
    element[0].scrollIntoView();
});

このコードは、ユーザーがURLのハッシュ部分(例:#section2)を変更すると、それに対応する要素を探して自動スクロールします。

しかしlocation.hashは完全にユーザーの入力で制御可能なため、悪意ある入力を$()関数に渡すことでHTML要素やスクリプトの挿入が可能になります。


🧪 攻撃例

以下のようなiframeを用いて、ユーザーの操作なしでhashchangeイベントを発生させ、XSSを実行させることができます。

<iframe src="https://vulnerable-website.com#" onload="this.src+='<img src=1 onerror=alert(1)>'">
</iframe>

この攻撃の流れは以下のとおりです:

  1. iframeはまず空のハッシュで脆弱なページを読み込みます(#だけ)。
  2. onloadイベントがトリガーされると、srcに悪意あるHTML(<img onerror=alert(1)>)を含むハッシュを追加します。
  3. hashchangeイベントが発生し、$(location.hash)が実行されてXSSが成立します。

🧱 jQueryの対応と注意点

近年のjQueryでは、セレクターの入力が#で始まる場合、HTMLタグとしての解釈を防ぐようにパッチが適用されています。これにより、$(location.hash)のような直接的な攻撃は難しくなっています。

ただし、次の点に注意が必要です:

  • location.hash以外の入力を使って$()に渡す場合(例えばクエリパラメータ)にはまだ脆弱性が残る可能性があります。
  • 古いバージョンのjQueryを使用しているアプリケーションは今でもこの脆弱性を抱えていることがあります。

✅ 対策

  • 常にjQueryを最新版にアップデートする。
  • ユーザー入力を直接DOM操作に使用しない。
  • HTML挿入が可能なセレクター($()など)への入力は必ず検証・サニタイズする。
  • CSP(Content Security Policy)の導入により、インラインスクリプトの実行を防止する。

🔍 まとめ

このようなDOM XSSのパターンは、特に古いコードベースやレガシーライブラリを利用しているサイトで今なお多く見られます。$()セレクターとユーザー入力の組み合わせは極めて危険です。

セキュリティテスト時にはhashchangeイベントやiframeを用いた自動トリガーにも注目し、DOMの振る舞いを詳細に観察することが重要です。

Best regards, (^^ゞ