Google Chromeの大規模な広告ブロック対策アップデートの回避策を見つけた方法、ただし今は修正済み
Google Chromeは、拡張機能の仕様をManifest V2(MV2)からManifest V3(MV3)へと移行しました。この移行に伴い、拡張機能がウェブサイトへのリクエストを動的にブロックする「webRequestBlocking」というAPIが利用できなくなりました。多くの広告ブロッカーはこのWebRequestBlockingに依存していたため、MV3への移行は広告ブロッカーに大きな影響を与えるとされていましたが、Derin Eryılmaz氏が、このMV3の制約を回避してwebRequestBlockingを有効にできるバグを2023年に発見したと報告しています。
How I found a bypass in Google's big anti-adblock update
https://0x44.xyz/blog/web-request-blocking/Chrome拡張機能はJavaScriptで記述されていますが、そのAPIはブラウザ内部のC++機能と連携する「バインディング」という仕組みで動作します。過去、GoogleはAPIの一部をJavaScriptファイルで処理していましたが、ウェブページからAPIの挙動を不正に操作される脆弱(ぜいじゃく)性が発見されたため、ほとんどのAPIバインディングをC++に移行しました。しかし、「chrome.webRequest」を含む一部のAPIでは、JavaScriptバインディングが引き続き使用されており、これが今回のバグの根本的な原因となりました。
MV3では、「webRequest.onBeforeRequest」イベントでリクエストをブロックするための以下のようなオプションが使用できなくなりました。これは最後の「blocking」部分で「webRequestBlocking」がMV3では許可されないためです。
chrome.webRequest.onBeforeRequest.addListener(() => {
return { cancel: true }
}, { urls: ['*://*.example.com/*'] }, ['blocking'])
しかし、このイベントの実装にはJavaScriptのクラスが使われており、そのコンストラクタが外部から呼び出し可能で、これを利用すると、独自のプロパティを持つ偽のイベントオブジェクトを生成できるようになっていました。 発見されたバグは、この偽イベントの生成時に「opt_webViewInstanceId」というパラメータを悪用するものでした。このパラメータは、かつてChromeプラットフォームアプリがWebView内の通信を制御するために「webRequestBlocking」を使うことを許可するためのもので、このIDが設定されたイベントはパーミッションチェックが免除される仕様でした。ただし、ブラウザがこのIDを持つイベントの生成元を検証していなかったとのこと。
let WebRequestEvent = chrome.webRequest.onBeforeRequest.constructor
// opt_webViewInstanceId is the 5th argument
let fakeEvent = new WebRequestEvent("webRequest.onBeforeRequest", 0, 0, 0, 1337)
fakeEvent.addListener(() => {
return { cancel: true }
}, { urls: ['*://*.example.com/*'] }, ['blocking'])
そのため、通常の拡張機能でも「opt_webViewInstanceId」に任意の数値を指定することでパーミッションチェックを回避し、MV3環境下でリクエストのブロッキング機能を有効にすることができました。この問題は、2020年に非推奨となったプラットフォームアプリ向けの古いコードが、2023年時点でも残存していたことに起因しており、Eryılmaz氏は「古いコードがいかにしてバグにつながるのかがよくわかる事例」と述べています。
このバグを悪用すると、「chrome.webRequest.onBeforeRequest」を偽のイベントに置き換えるだけで、MV3環境で機能する広告ブロッカーを開発することが可能でした。発見者のEryılmaz氏は、「このバグを利用して、MV3でのすべてのインスタンスを偽のイベントに置き換えるだけで、完璧に動作する広告ブロッカーを作成できたはず」としながらも、広告ブロッカーの作り方がわからなかったためにGoogleへこのバグを2023年8月に報告した、と冗談交じりに述べています。 その結果、このバグはChrome 118で修正され、「opt_webViewInstanceId」を使用する拡張機能が適切なパーミッションを持つかどうかの検証が追加されました。しかし、Googleはこの報告をセキュリティ問題とは見なさず、バグ発見の報奨金は支払われなかったとのこと。その理由として、このバグは拡張機能が元々アクセス権を持たないデータへのアクセスを許可するものではない、と判断されたためです。
Eryılmaz氏は「このバグから得た私の収益です」と述べて以下の画像を公開。ただし、同じく2023年にEryılmaz氏が発見したCVE-2023-4369については、報告後に1万ドル(約145万円)の報酬金が支払われたそうです。
・関連記事 GoogleがChromeの広告ブロックの新方式「マニフェスト V3」を正式発表、拡張機能やPWAの改善などの新情報も - GIGAZINE
Googleがウェブ上の広告を非表示にする広告ブロック機能をChromeなどで無効化するための施策を進める - GIGAZINE
Chrome拡張機能の新仕様「Manifest V3」は非常に有害だと電子フロンティア財団が非難 - GIGAZINE
Googleが拡張機能仕様「Manifest V2」の段階的廃止を開始 - GIGAZINE
GoogleがManifest V2の非推奨化を再開、Chromeで将来的に広告ブロッカーを制限する計画が前進 - GIGAZINE
Googleが「uBlock Originのサポートは終了しました」とウソをついているとネットが騒然、広告ブロッカーを使い続ける方法はコレ - GIGAZINE