OWASP カテゴリ: MASVS-PLATFORM: プラットフォームのインタラクション
概要
JavaScript ブリッジとも呼ばれるネイティブ ブリッジは、
WebView とネイティブ Android コード間の通信を容易にします。
addJavascriptInterface
メソッドを使用します。これにより、WebView で実行されている JavaScript コードと Android アプリの Java コードとの間で双方向通信が可能になります。addJavascriptInterface
メソッドは、WebView のすべてのフレームに Java オブジェクトを公開します。どのフレームもオブジェクト名にアクセスして、そのメソッドを呼び出すことができます。ただし、WebView 内で呼び出し元のフレームのオリジンをアプリが検証するメカニズムはありません。そのため、コンテンツの信頼性が不明確なままとなり、セキュリティ上の懸念が生じます。
ネイティブ ブリッジは、HTML メッセージ チャネルに
Android の WebViewCompat.postWebMessage
または
JavaScript と通信するための WebMessagePort.postMessage
Window.postMessage
。WebViewCompat.postWebMessage
と WebMessagePort.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 が誤って公開される可能性があります。
影響
addJavascriptInterface
、postWebMessage
、postMessage
メソッドは、悪意のある行為者が悪用して、制御するコードにアクセスしたり、操作したり、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:usesCleartextTraffic
を false
に設定することで、暗号化されていない接続を
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()
を設定する場合は、ターゲット送信元として * を使用しないで、信頼できるドメインからのメールのみを許可するようにします。代わりに、想定される送信ドメインを明示的に指定します。
リソース
- postMessage() のベスト プラクティス
- addJavascriptInterface のドキュメント
- postMessage() のドキュメント
- WebMessagePort.postMessage() のドキュメント
- WebViewClient.shouldInterceptRequest のドキュメント
- addJavascriptInterface に関するセキュリティに関するアドバイスのドキュメント
- clearCache のドキュメント
- removeJavascript のドキュメント
- WebView で JavaScript を有効にする