WebView - Ponti nativi

Categoria OWASP: MASVS-PLATFORM: Platform Interaction

Panoramica

Un bridge nativo, a volte noto come bridge JavaScript, è un meccanismo che facilita la comunicazione tra un componente WebView e il codice Android nativo, ottenuto utilizzando il addJavascriptInterface metodo. Ciò consente la comunicazione bidirezionale tra il codice JavaScript in esecuzione nel componente WebView e il codice Java dell'applicazione Android. Il metodo addJavascriptInterface espone un oggetto Java a tutti i frame di un componente WebView e qualsiasi frame può accedere al nome dell'oggetto e chiamare i metodi su di esso. Tuttavia, non esiste un meccanismo per l'applicazione per verificare l'origine del frame chiamante all'interno del componente WebView, il che solleva problemi di sicurezza in quanto l'attendibilità dei contenuti rimane indeterminata.

Un bridge nativo può essere implementato anche con i canali di messaggi HTML utilizzando WebViewCompat.postWebMessage di Android o WebMessagePort.postMessage per comunicare con Window.postMessage di JavaScript. WebViewCompat.postWebMessage e WebMessagePort.postMessage possono accettare messaggi JavaScript inviati tramite Window.postMessage che verranno eseguiti all'interno del componente WebView.

Esistono diversi rischi associati ai bridge nativi:

  • Bridge basati su JavascriptInterface:
    • Il metodo addJavascriptInterface inserisce un oggetto Java fornito in ogni frame del componente WebView, inclusi gli iframe, il che significa che è suscettibile di attacchi da parte di terze parti malintenzionate che inseriscono frame in un sito web legittimo. Le applicazioni che hanno come target il livello API 16 o precedente sono particolarmente a rischio di attacco perché questo metodo può essere utilizzato per consentire a JavaScript di controllare l'applicazione host.
    • La visualizzazione di contenuti non attendibili forniti dall'utente nei componenti WebView abilitati per il bridge nativo consente attacchi di tipo "cross-site scripting" (XSS).
  • Bridge basati su MessageChannel:
    • La mancanza di controlli di origine sugli endpoint del canale di messaggi significa che i messaggi verranno accettati da qualsiasi mittente, inclusi quelli contenenti codice dannoso.
    • È possibile esporre accidentalmente Java a JavaScript arbitrario.

Impatto

Gli attori malintenzionati possono sfruttare i metodi addJavascriptInterface, postWebMessage e postMessage per accedere, manipolare o inserire codice che controllano in un componente WebView. Ciò potrebbe comportare il reindirizzamento degli utenti a siti dannosi, il caricamento di contenuti dannosi o l'esecuzione di codice dannoso sui loro dispositivi in grado di estrarre dati sensibili o ottenere l'escalation dei privilegi.

Rischio: rischi di addJavascriptInterface

WebView implementa le funzionalità di base di un browser, come il rendering delle pagine, la navigazione e l'esecuzione di JavaScript. WebView può essere utilizzato all'interno di un'applicazione per visualizzare contenuti web come parte di un layout di attività. L'implementazione di un bridge nativo all'interno di un componente WebView utilizzando il metodo addJavascriptInterface può creare problemi di sicurezza come lo scripting cross-site (XSS) o consentire agli utenti malintenzionati di caricare contenuti non attendibili tramite l'inserimento dell'interfaccia e manipolare l'applicazione host in modi non previsti, eseguendo codice Java con le autorizzazioni dell'applicazione host.

Mitigazioni

Viene disattivato JavaScript

Negli scenari in cui WebView non richiede JavaScript, non chiamare setJavaScriptEnabled all'interno di WebSettings (ad esempio, durante la visualizzazione di contenuti HTML statici). Per impostazione predefinita, l'esecuzione di JavaScript è disattivata in WebView.

Rimuovi l'interfaccia JavaScript durante il caricamento di contenuti non attendibili

Assicurati che gli oggetti dell'interfaccia JavaScript vengano rimossi chiamando removeJavascriptInterface prima che vengano caricati contenuti non attendibili dal componente WebView. Ad esempio, questa operazione può essere eseguita in una chiamata a shouldInterceptRequest.

Kotlin

webView.removeJavascriptInterface("myObject")

Java

webView.removeJavascriptInterface("myObject");

Carica solo contenuti web tramite HTTPS

Se devi caricare contenuti non attendibili, assicurati che il componente WebView carichi i contenuti web tramite una connessione criptata (consulta anche le nostre linee guida sulle comunicazioni in testo non criptato). Impedisci il caricamento iniziale della pagina su connessioni non criptate impostando android:usesCleartextTraffic su false in il file AndroidManifest o non consentire il traffico HTTP in una configurazione di sicurezza di rete. Per ulteriori informazioni, consulta la documentazione di usesCleartextTraffic.

Xml

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

Per assicurarti che i reindirizzamenti e l'ulteriore navigazione dell'app non avvengano su traffico non criptato, controlla lo schema HTTP in loadUrl o shouldInterceptRequest:

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);
        }
    }
}

Convalida i contenuti non attendibili

Se in un componente WebView vengono caricati link esterni, convalida sia lo schema sia l'host (domini della lista consentita). I domini non inclusi nella lista consentita devono essere aperti dal browser predefinito.

Non caricare contenuti non attendibili

Se possibile, carica in WebView solo gli URL con ambito limitato e i contenuti di proprietà dello sviluppatore dell'app.

Non esporre dati sensibili

Se la tua applicazione accede a dati sensibili con un componente WebView, valuta la possibilità di utilizzare il clearCache metodo per eliminare tutti i file archiviati localmente prima di utilizzare l' interfaccia JavaScript. Puoi anche utilizzare le intestazioni lato server, ad esempio no-store, per indicare che un'applicazione non deve memorizzare nella cache contenuti specifici.

Non esporre funzionalità sensibili

Se la tua applicazione richiede autorizzazioni sensibili o raccoglie dati sensibili, assicurati che venga chiamata dal codice all'interno dell'applicazione e che agli utenti venga fornita una divulgazione ben visibile. Evita di utilizzare le interfacce JavaScript per operazioni sensibili o dati utente.

Effettua il targeting del livello API 21 o superiore

Un modo sicuro per utilizzare il metodo addJavascriptInterface è effettuare il targeting del livello API 21 o superiore assicurandosi che il metodo venga chiamato solo quando è in esecuzione sul livello API 21 o superiore. Prima dell'API 21, JavaScript poteva utilizzare la reflection per accedere ai campi pubblici di un oggetto inserito.


Rischio: rischi di MessageChannel

La mancanza di controllo dell'origine in postWebMessage() e postMessage() potrebbe consentire agli utenti malintenzionati di intercettare i messaggi o inviare messaggi ai gestori nativi.

Mitigazioni

Quando configuri postWebMessage() o postMessage(), consenti solo i messaggi provenienti da domini attendibili evitando l'uso di * come origine di destinazione e specificando invece esplicitamente il dominio di invio previsto.


Risorse