その開発者は、同僚が新しい build ツールについて話していた Discord チャンネルに貼られたリンクを開きました。何もクリックせず、何も入力せず、何も ダウンロードしていません。ページはうまく表示されず、古い font がどうのこうのというメッセージが出ただけです。五分後、ノート PC が見慣れないプロセス活動を報告していました。レンダリングのわずか 数百ミリ秒のあいだに、ページは WebGL renderer のメモリバグを突いていたのです。
drive-by download はブラウザでもっとも目立たない攻撃カテゴリです。ユーザー側の 操作は一切必要ありません。被害者がページを開いた瞬間、exploit はもう動いています。2000 年代初頭に ActiveX コンポーネントで行われていたことは、いまや JavaScript エンジン、WebGL、WebAssembly、メディアコーデックの脆弱性を突く 形に移っています。現代のブラウザは堅牢になりましたが、攻撃面は はるかに広がりました。
なぜクリックが不要なのか
ブラウザは単なるページの renderer ではありません。読み込んだすべてのページに JavaScript を実行させ、GPU にグラフィックを送り、動画 stream をデコードし、WebAssembly のバイナリをローカルで走らせる 本格的なランタイムです。これらはすべて、HTML が parser に届いた瞬間に自動で動き始めます。
drive-by download はまさにこのパイプラインに入り込んできます。配列の インデックスが境界を越えることを許してしまう JavaScript エンジンのバグ、Canvas API の race condition、メモリオーバーフローを引き起こす壊れた動画 フレーム、どれもが入り口です。ブラウザが exploit のコードを実行するのは、それがページの中身だからであって、ユーザーが 何かを許可したからではありません。
ブラウザのサンドボックスは多くの試みを受け止めます。本当に危険 なのは連鎖型の exploit です。JavaScript エンジンのバグで任意のメモリへアクセスし、二つ目のバグで サンドボックスを抜け、三つ目のバグでシステム権限まで昇格させます。 こうしたチェーンは攻撃者にとってコストが高いものの、大規模な キャンペーンに実際にしっかり組み込まれています。
現代の exploit が狙う場所

JavaScript の JIT。V8 や SpiderMonkey のような現代的なエンジンは、ホットな関数を実行時にマシン コードへコンパイルします。JIT コンパイラにバグがあると不正なコードが生成され、ブラウザはそれを フル権限で実行してしまいます。ここ数年で exploit されたブラウザのバグの多くは、この層から出ています。
WebGL と WebGPU。シェーダは フィルタを通らずに GPU へ渡されます。グラフィックドライバは昔からバグが多く、WebGL の exploit はブラウザのサンドボックスを抜ける定番ルートです。
メディアのデコード。動画・音声のコーデックは 巨大な入力空間を C や C++ で扱います。コーデック内部のメモリ破壊はそのまま直接的な コード実行につながることが多いです。2023 年に iMessage に対して使われた有名な BLASTPASS exploit は画像パーサを突いたものでしたが、同じ種類の問題はブラウザにも 存在します。
WebAssembly と Web Workers。独自のメモリ モデルを持つ並列スレッドは便利な反面、メモリバグが 突かれる新たな面でもあります。
そのページが画面に届く経路
drive-by のページはどこからともなく現れるわけではなく、配信されます。 主な経路は三つ。malvertising、watering hole 攻撃、そして侵害された正規サイトです。
malvertising はもっとも安く済む経路です。仕込まれたページは広告バナーの iframe の中に潜み、ホストページを読み込んだ全員に届きます。詳しくは Malvertising: When the Ad Is the Attackを参照してください。watering hole 攻撃はもっと的を絞っています。攻撃者は、狙った層がよく訪れる とわかっているサイト(業界ニュース、開発者向けドキュメント、 コミュニティのフォーラムなど)を侵害し、そこに exploit を仕込みます。
三つ目は、直接侵害された正規サイトです。乗っ取られた WordPress プラグイン、盗まれた CDN アカウント、改ざんされたビルドフック、どれか一つあれば信頼されている サイトにスクリプトを注入できてしまいます。訪問者からは その違いを見分ける術がありません。
patch と rollout のあいだの時間差

Chrome、Firefox、Safari は重大な脆弱性に対する patch を数日で出します。しかし、update が手元に届くのは、ブラウザがそれを取得して再起動したとき です。デスクトップではふつう 24 時間、Android では数週間、 管理された enterprise 環境では、rollout の窓次第で一か月に及ぶこともあります。
攻撃者はこの窓を細部まで把握しています。disclosure の日を待ち、patch を diff して実際の変更箇所を突き止め、数時間で exploit を組み上げます。短くも非常に実入りのよい期間、世間は 脆弱だと分かったまま放置されることになります。よく管理された 環境にいても、その数時間はユーザーも危険にさらされます。
自動 update も助けにはなりますが、万能ではありません。五日間再起動されていない ブラウザは、patch がとっくにダウンロード済みでも、古い build で走り続けます。
回避ではなく封じ込め
web を使っている以上、drive-by download を確実に回避することはできません。信頼できるサイトは安全だと いう前提も成り立ちません。広告ネットワーク、supply chain 攻撃、zero-day は、もっとも信頼されているサイトにも及ぶからです。力点は 「避ける」から「封じ込める」へ移ります。
隔離されたブラウザセッションでも exploit を本気で受け止める姿勢は変わりませんが、攻撃が落ちるのは 手元の OS ではない環境です。payload はセッション終了後に破棄されるコンテナの中に着地します。 ノート PC はきれいなままです。普段使いのブラウザの update を素早く回すこと、そして未知のリンクを業務用マシンで開く 必要はないと割り切ること。この二つを組み合わせれば、実質的な リスクは大きく縮みます。zero-day のサイクルについての背景は Zero-Day Exploitsを参照してください。
どんな端末でも、デスクトップ並みの快適さを。
Browser.lol を無料で試して、スマホやタブレットでも PC 並みの快適さを体感してみませんか?
デスクトップブラウザを試すダウンロード不要・どんな端末でも動作



