FlawOpen

flawopen.com/Android WebView のセキュリティ/addJavascriptInterface

Android addJavascriptInterface:リスクと安全な使い方

リファレンスページ
要点

addJavascriptInterface を使う WebView は、特権境界として扱ってください。Android はオブジェクトをすべての frame に注入し、アプリはどの frame がメソッドを呼んだか判別できません。攻撃者が制御する JavaScript がいずれかの frame に到達すると、アプリの権限で公開メソッドを呼び出す可能性があります。ブリッジ付き WebView にはアプリが管理するコンテンツだけを読み込み、未信頼ページはブリッジのない別の WebView で開きます。

ブリッジが XSS の影響を変える理由

ブリッジは JavaScript からホストアプリを呼び出す入口になります。Android は iframe を含むすべての frame にオブジェクトを公開し、addJavascriptInterface は呼び出し元 frame の origin を検証しません。そのため、注入されたスクリプトが注釈付きメソッドに到達する可能性があります。実行可能な操作はメソッドとアプリ側の認可チェックで決まります。target API が 16 以下のアプリでは、すべての public メソッドが公開される、より深刻な旧仕様を Android が説明しています。API 17 以降は @JavascriptInterface が必要ですが、この注釈で未信頼コンテンツが安全になるわけではありません。

未信頼ページからブリッジを切り離す

危険 — 同じ WebView でブリッジと未信頼ページを扱う
webView.addJavascriptInterface(
  NativeBridge(), "Android"
)
webView.loadUrl(untrustedUrl)
より安全 — 信頼済みと未信頼のコンテンツを分離する
// この WebView はアプリ管理の同梱 UI 専用です。
trustedWebView.settings.javaScriptEnabled = true
trustedWebView.addJavascriptInterface(
  NativeBridge(), "Android"
)
trustedWebView.loadUrl("file:///android_asset/index.html")

// 別の WebView でリモートまたはユーザー管理ページを扱います。
untrustedWebView.removeJavascriptInterface("Android")
untrustedWebView.settings.javaScriptEnabled = false
// HTTPS と明示的なホスト allowlist を検証します。
untrustedWebView.loadUrl(validatedHttpsUrl)

最も強い境界はアーキテクチャです。ブリッジ付き WebView を、リモート、ユーザー生成、または攻撃者の影響を受けるページへ遷移させないでください。未信頼コンテンツの読み込みが避けられない場合は、読み込み前にインターフェースを削除し、必要でない限り JavaScript を無効にした別の WebView を使います。Android によると、注入オブジェクトはすべての frame から利用でき、削除は次のページ読み込み後に反映されます。HTTPS は通信を保護しますが、ホストやコンテンツを信頼できるものにはしません。URL の scheme と host を検証し、許可リスト外のリンクはシステムブラウザーで開きます。ブリッジメソッドを最小限にし、引数を検証し、呼び出し元ページを信頼せずネイティブコードで認可してください。

Android WebView ブリッジのセキュリティ FAQ

API 17 以降なら addJavascriptInterface は安全ですか?

いいえ。API 17 以降は @JavascriptInterface が付いた public メソッドだけを公開しますが、呼び出し元 frame の origin は検証せず、攻撃者が制御するコンテンツも信頼済みにはなりません。アプリが管理するコンテンツだけを読み込む WebView にブリッジを限定してください。

参考資料

関連項目 クロスサイトスクリプティング(XSS、CWE-79)の仕組みと各言語での防ぎ方 — flawopen.com Angular の XSS 対策:安全な既定動作とバイパス API MIME sniffing XSS:Content-Type と nosniff CSP と出力エスケープ:両方必要ですか? ReactのdangerouslySetInnerHTMLは安全? DOMPurifyだけでinnerHTMLは安全? Markdown のレンダリングは XSS に安全?