「javascript:」という名のトロイの木馬 ― URLスキーム攻撃からWebサイトを守る方法
こんにちは。現場の最前線でセキュリティと向き合っているエンジニアです。
皆さんは、Webサイトの入力フォームに「悪意のあるスクリプトを書き込まれたら大変だ!」と、必死にタグの除去(エスケープ)をした経験はありませんか? それは素晴らしい心がけです。でも実は、もっと「盲点」になりやすい場所があります。
それが、リンク先(href)や画像ソース(src)の属性です。今回は、あまりにも身近すぎて見落とされがちな「URLスキーム」を悪用したXSS(クロスサイトスクリプティング)について、一緒に紐解いていきましょう。
—
1. なぜ「javascript:」が危険なの?
まずはイメージしてみてください。あなたの家の玄関に「このボタンを押すと、自動的に鍵が開く」という便利な装置があったとします。本来は「自分の部屋のドア」を開けるためのものですが、もし泥棒がそこに「他人の家に入る合鍵」を差し込める仕組みがあったらどうなるでしょう?
Webサイトにおけるhref属性やsrc属性は、本来「https://…」のようなURLを入れる場所です。しかし、ブラウザは親切すぎるあまり、ここにjavascript:という文字列が入っていると、「おっ、これはURLじゃなくて命令コードだな! 実行しなきゃ!」と判断して動かしてしまうのです。
攻撃のメカニズム
例えば、ユーザーが自由に入力できる「ウェブサイトのURL」入力欄があるとします。攻撃者はそこにこんな入力をします。
javascript:alert(‘あなたのクッキーを盗みました!’);
サイト側がこれをそのままサイトへと出力してしまうと、クリックした瞬間に被害者のブラウザで攻撃者のコードが実行されてしまいます。これが、URLスキームを用いたXSS攻撃です。
—
2. 泥棒を入れないための「ホワイトリスト」作戦
では、どうすれば防げるのでしょうか? 一番確実な方法は、「信頼できるプロトコル以外は一切お断りする」という門番を置くことです。
玄関に「許可された鍵以外は受け付けません」というセンサーを置くイメージですね。これを技術的には「ホワイトリスト方式」と呼びます。
実践的な防御コード(JavaScript例)
ユーザーが入力したURLをリンクとして使う前に、必ずチェックを通しましょう。
function sanitizeUrl(url) {
// 許可するプロトコルをリスト化しておく
const allowedProtocols = [‘http:’, ‘https:’, ‘mailto:’];
try {
const parsedUrl = new URL(url);
// プロトコルが許可リストに含まれているかチェック
if (allowedProtocols.includes(parsedUrl.protocol)) {
return url; // 安全ならそのまま返す
}
} catch (e) {
// URLとして不正な形式なら、とりあえず空にするなどの処置を
return ‘#’;
}
return ‘#’; // 不審なスキームならリンクを無効化する
}
このように、javascript:という文字列を入り口でシャットアウトすることが、最大の防御になります。
—
3. もう一つの壁:CSP(コンテンツセキュリティポリシー)
コードの修正に加えて、サーバー側で「うちのサイトは、こういうルールで動くからね!」とブラウザに宣言するCSP(Content Security Policy)を設定するのも非常に効果的です。
HTTPレスポンスヘッダーに以下のような設定を入れることで、たとえ攻撃コードが紛れ込んでも、ブラウザ側が「いや、このサイトはインラインのスクリプト実行は禁止されているから動かさないよ」とブロックしてくれます。
CSPヘッダーの例
Content-Security-Policy: default-src ‘self’; script-src ‘self’;
- default-src ‘self’: 自分のドメイン以外の読み込みを原則禁止。
- script-src ‘self’: スクリプトも自分のサーバーからしか読み込まない。
これで、外部から持ち込まれた悪意あるスクリプトは、ほとんど無力化されます。
—
まとめ:セキュリティは「疑うこと」から始まる
今回学んだポイントを整理しましょう。
1. 「URLなら安全」という思い込みを捨てる: hrefやsrcも、立派な攻撃経路になり得ます。
2. ホワイトリストで守る: 許可されたプロトコル(http/httpsなど)だけを通すチェックを徹底しましょう。
3. CSPで多重防御: サーバーの設定で、ブラウザに「ルール」を教え込みましょう。
セキュリティ対策は、一度やって終わりではありません。泥棒は常に新しい合鍵を探しています。でも、こうして一つずつ仕組みを理解していけば、皆さんのサイトはもっと強固で、ユーザーに愛される場所になるはずです。
「難しそうだな」と思ったら、まずは今日紹介した「ホワイトリスト方式」の考え方だけ覚えて帰ってください。それだけでも、あなたのサイトの守備力は格段に上がりますよ。一歩ずつ、一緒に強くなっていきましょう!
コメント