WebView - ネイティブ ブリッジ

OWASP カテゴリ: MASVS-PLATFORM: プラットフォームのインタラクション

概要

JavaScript ブリッジとも呼ばれるネイティブ ブリッジは、 WebView とネイティブ Android コード間の通信を容易にします。 addJavascriptInterface メソッドを使用します。これにより、WebView で実行されている JavaScript コードと Android アプリの Java コードとの間で双方向通信が可能になります。addJavascriptInterface メソッドは、WebView のすべてのフレームに Java オブジェクトを公開します。どのフレームもオブジェクト名にアクセスして、そのメソッドを呼び出すことができます。ただし、WebView 内で呼び出し元のフレームのオリジンをアプリが検証するメカニズムはありません。そのため、コンテンツの信頼性が不明確なままとなり、セキュリティ上の懸念が生じます。

ネイティブ ブリッジは、HTML メッセージ チャネルに Android の WebViewCompat.postWebMessage または JavaScript と通信するための WebMessagePort.postMessage Window.postMessageWebViewCompat.postWebMessageWebMessagePort.postMessage は、WebView 内で実行される Window.postMessage を介して送信された JavaScript メッセージを受け入れることができます。

ネイティブ ブリッジに関連するリスクは複数あります。

  • JavaScriptInterface ベースのブリッジ: <ph type="x-smartling-placeholder">
      </ph>
    • addJavascriptInterface メソッドは、iframe を含む WebView のすべてのフレームに指定された Java オブジェクトを挿入します。つまり、悪意のある第三者が正当なウェブサイトにフレームを挿入する攻撃を受けやすくなります。API レベル 16 以前を対象とするアプリは、このメソッドを使用して JavaScript がホストアプリを制御できるようにできるため、特に攻撃のリスクが高くなります。
    • 信頼できないユーザー提供コンテンツをネイティブ ブリッジ対応の WebView に反映させる クロスサイト スクリプティング(XSS)攻撃が可能になります。
  • MessageChannel ベースのブリッジ: <ph type="x-smartling-placeholder">
      </ph>
    • メッセージ チャネル エンドポイントで送信元チェックが行われないため、悪意のあるコードを含む送信者を含む、すべての送信者からメッセージが受け入れられます。
    • 任意の JavaScript に Java が誤って公開される可能性があります。

影響

addJavascriptInterfacepostWebMessagepostMessage メソッドは、悪意のある行為者が悪用して、制御するコードにアクセスしたり、操作したり、WebView に挿入したりできます。その結果、ユーザーが悪意のあるサイトにリダイレクトされたり、 悪意のあるコンテンツの読み込みや、不正なコードをデバイスでの 機密データの抽出や権限昇格が可能になります。

リスク: addJavascriptInterface のリスク

WebView は、ページ レンダリングなどのブラウザの基本機能を実装します。 ナビゲーション、JavaScript の実行ですWebView は、アプリ内で使用して、アクティビティ レイアウトの一部としてウェブ コンテンツを表示できます。addJavascriptInterface メソッドを使用して WebView 内にネイティブ ブリッジを実装すると、クロスサイト スクリプティング(XSS)などのセキュリティ問題が発生する可能性があります。また、攻撃者がインターフェース インジェクションによって信頼できないコンテンツを読み込み、ホスト アプリケーションを意図しない方法で操作し、ホスト アプリケーションの権限で Java コードを実行する可能性があります。

リスクの軽減

JavaScript を無効にする

WebView で JavaScript を必要としないシナリオでは、WebSettings 内で setJavaScriptEnabled を呼び出さないでください(静的 HTML コンテンツを表示している場合など)。デフォルトでは、JavaScript の実行は WebView

信頼できないコンテンツを読み込むときに JavaScript インターフェースを削除する

次の呼び出しによって JavaScript インターフェースのオブジェクトを確実に削除する removeJavascriptInterface: 信頼できないコンテンツが WebViewたとえば、これは呼び出しで行うことができます。 shouldInterceptRequest

Kotlin

webView.removeJavascriptInterface("myObject")

Java

webView.removeJavascriptInterface("myObject");

HTTPS 経由でウェブ コンテンツのみを読み込む

信頼できないコンテンツを読み込む必要がある場合は、WebView でウェブ コンテンツが読み込まれるようにします。 (Google のクリアテキスト ガイド、 コミュニケーション)。最初のページ読み込みが行われないようにする android:usesCleartextTrafficfalse に設定することで、暗号化されていない接続を AndroidManifest ファイル、またはネットワーク セキュリティで HTTP トラフィックを禁止する config詳細については、usesCleartextTraffic のドキュメントをご覧ください。 情報です。

XML

<application
    android:usesCleartextTraffic="false">
    <!-- Other application elements -->
</application>

暗号化されていないトラフィックでリダイレクトとアプリのブラウジングが実行されないようにするには、loadUrl または shouldInterceptRequest で HTTP スキームを確認します。

Kotlin

fun loadSecureUrl(webView: WebView?, url: String?) {
    webView?.let { wv ->  // Ensure valid WebView and URL
        url?.let {
            try {
                val uri = URI(url)
                if (uri.scheme.equals("https", ignoreCase = true)) { // Enforce HTTPS scheme for security
                    wv.loadUrl(url)
                } else {
                    // Log an error or handle the case where the URL is not secure
                    System.err.println("Attempted to load a non-HTTPS URL: $url")
                }
            } catch (e: Exception) {
                // Handle exception for improper URL format
                System.err.println("Invalid URL syntax: $url")
            }
        }
    }
}

Java

public void loadSecureUrl(WebView webView, String url) {
    if (webView != null && url != null) { // Ensure valid WebView and URL
        try {
            URI uri = new URI(url);
            String scheme = uri.getScheme();
            if ("https".equalsIgnoreCase(scheme)) { // Enforce HTTPS scheme for security
                webView.loadUrl(url);
            } else {
                // Log an error or handle the case where the URL is not secure
                System.err.println("Attempted to load a non-HTTPS URL: " + url);
            }
        } catch (URISyntaxException e) {
            // Handle exception for improper URL format
            System.err.println("Invalid URL syntax: " + url);
        }
    }
}

信頼できないコンテンツを検証する

外部リンクが WebView に読み込まれる場合は、スキームとホストの両方を検証する (許可リストのドメイン)。許可リストに登録されていないドメインは、デフォルトのブラウザで開く必要があります。

信頼できないコンテンツを読み込まない

可能であれば、範囲を限定した URL とアプリが所有するコンテンツのみを読み込む WebView に統合します

機密データを公開しない

アプリが WebView を使用して機密データにアクセスする場合は、 clearCache メソッドを使用して、Cloud Storage バケットを使用する前に、ローカルに保存されているファイルをすべて削除します。 JavaScript インターフェースを使用します。また、no-store などのサーバーサイド ヘッダーを使用して、アプリが特定のコンテンツをキャッシュしないように指示することもできます。

機密性の高い機能は公開しないでください

アプリで機密情報に関わる権限を必要とする機能や、機密情報を収集する機能がある場合は、アプリ内のコードから呼び出されるようにし、ユーザーに目立つように開示してください。JavaScript インターフェースを 機密データを検出することもできます。

対象 API レベル 21 以降

addJavascriptInterface メソッドを安全に使用するための 1 つの方法は、API レベル 21 以上をターゲットにして、API レベル 21 以上で実行されている場合にのみメソッドが呼び出されるようにすることです。API 21 より前は、JavaScript はリフレクションを使用して、挿入されたオブジェクトのパブリック フィールドにアクセスできました。


リスク: MessageChannel のリスク

postWebMessage()postMessage() に送信元の制御がないため、攻撃者がメッセージをインターセプトしたり、ネイティブ ハンドラにメッセージを送信したりできる可能性があります。

リスクの軽減

postWebMessage() または postMessage() を設定する場合は、ターゲット送信元として * を使用しないで、信頼できるドメインからのメールのみを許可するようにします。代わりに、想定される送信ドメインを明示的に指定します。


リソース