こんにちは!セキュリティの世界へようこそ。
今日は、Webサイトの「裏側」でこっそり行われている、ちょっと厄介な「DOMベースXSS」という攻撃について、一緒に紐解いていきましょう。
「難しそう…」と思うかもしれませんが、大丈夫です。まずは身近な「家の防犯」に例えて、仕組みを直感的に理解することから始めましょう!
—
1. DOMベースXSSって、どんな「泥棒」なの?
皆さんの家には「郵便受け」がありますよね。外から誰でも手紙を入れられる、あれです。
DOMベースXSSを例えるなら、「郵便受けに偽造した『重要なお知らせ』を入れて、住人を騙して鍵を開けさせる泥棒」のようなものです。
Webサイトにおいて、URLの後ろにつくパラメーター(例:?name=ゲスト)は、まさに郵便受けです。本来は「ゲスト」という名前を表示するためのものですが、攻撃者はここに悪意のある「命令文」を忍ばせます。
Webブラウザがその命令文を鵜呑みにして、画面を書き換えてしまう…これがDOMベースXSSの正体です。
—
2. 攻撃の正体:「ソース」と「シンク」を見極める
セキュリティの世界では、データの流れを2つのキーワードで追いかけます。
- ソース(入り口): 外部からデータが入ってくる場所。
location.search(URLのパラメータ)などが代表的です。 - シンク(出口・危険な場所): データが実行される場所。ここが一番の「危ない場所」です。
例えば、以下のコードを見てください。
// ソース:URLのパラメータを取得
const params = new URLSearchParams(window.location.search);
const userName = params.get('name');
// シンク:受け取ったデータをそのままHTMLとして表示してしまう(危険!)
document.getElementById('welcome').innerHTML = "こんにちは、" + userName + "さん";
このコードの何が危ないか分かりますか?
もし攻撃者が ?name=<img src=x onerror=alert('ハックされました!')> というURLを作って誰かに踏ませたら、ブラウザは「imgタグ」として読み込もうとして失敗し、その瞬間にalertという命令(JavaScript)を実行してしまいます。
これが、家の鍵を勝手に開けられてしまう瞬間です。
—
3. 「DOMPurify」で防犯対策をしよう!
では、どう守ればいいのでしょうか?一番大切なのは、「入ってきたデータを、そのまま信用して実行しない」ことです。
ここで登場するのが「サニタイズ(浄化)」という技術です。掃除機でゴミを吸い取るように、データの中から悪意のある部分だけを取り除きます。そのための最強のツールが DOMPurify です。
対策したコード例
// 1. まずDOMPurifyを読み込みます(ライブラリとして追加)
// <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.0.6/purify.min.js"></script>
const params = new URLSearchParams(window.location.search);
const userName = params.get('name') || "ゲスト";
// 2. DOMPurifyを使って、危険なタグを無害化する
// 汚いデータ(userName)をきれいにしてから表示します
const cleanName = DOMPurify.sanitize(userName);
// 3. 安全な状態になったデータだけを画面に表示する
document.getElementById('welcome').innerHTML = "こんにちは、" + cleanName + "さん";
これだけで、たとえ攻撃者が悪意のあるタグを送り込んできても、DOMPurifyが「これは危険な部品ですね、取り除きますね」と無害な文字列に変換してくれるので、スクリプトが実行されることはありません。
—
4. 現場で使える「防御ヘッダー」という二重の鍵
コードを書く以外にも、Webサイト全体に「防犯カメラ」や「強固なドア」を設置することができます。それが「HTTPレスポンスヘッダー」です。
特に Content-Security-Policy (CSP) は強力です。サーバーからブラウザに対して、「このサイトでは、許可していない場所から持ってきたスクリプトは絶対に実行しないでね!」と命令を出すことができます。
例えば、Webサーバーの設定で以下のようなヘッダーを送るのが一般的です。
# すべてのスクリプトは自分自身のドメインからのみ許可する設定
Content-Security-Policy: default-src 'self'; script-src 'self';
これにより、もしコードのどこかにバグがあったとしても、外部から持ち込まれた悪意のあるスクリプトはブラウザによってブロックされます。二重の鍵をかける、とても大切な習慣です。
—
最後に:セキュリティは「泥臭い」積み重ね
今回はDOMベースXSSについて解説しましたが、セキュリティの現場では「どこからデータが入ってきて、どこで使われているか?」を一つずつ追いかける、地味で泥臭い調査が欠かせません。
でも、怖がる必要はありません!
1. ソースを疑う(外部からの入力はすべて悪意があるかもしれないと考える)
2. シンクを守る(innerHTMLなどを直接使わず、textContentなどを使うか、DOMPurifyで洗う)
3. ヘッダーで守る(CSPを設定する)
これらを意識するだけで、あなたの作るWebサイトはグッと強固なものになります。一歩ずつ、一緒に学んでいきましょうね!
何か分からないことがあれば、いつでもまた聞きに来てください。応援しています!
コメント