WebView: Puentes nativos

Categoría de OWASP: MASVS-PLATFORM: Interacción con la plataforma

Descripción general

Un puente nativo, a veces conocido como puente JavaScript, es un mecanismo que y facilita la comunicación entre un WebView y código nativo de Android, lo que se logra mediante con el método addJavascriptInterface Esto permite la comunicación bidireccional entre el código JavaScript que se ejecuta en WebView y el código Java de la aplicación para Android. El método addJavascriptInterface expone un objeto Java a todos los fotogramas de una WebView, y cualquier fotograma puede acceder al nombre del objeto y llamar a métodos en él. Sin embargo, no existe un mecanismo para que la aplicación verificar el origen del fotograma de llamada dentro de WebView, lo que aumenta la seguridad inquietudes, ya que la confiabilidad del contenido sigue siendo indeterminada.

También se puede implementar un puente nativo con canales de mensajes HTML usando WebViewCompat.postWebMessage o WebMessagePort.postMessage para comunicarse con JavaScript Window.postMessage WebViewCompat.postWebMessage y WebMessagePort.postMessage puede aceptar mensajes de JavaScript enviados a través de Window.postMessage, que se ejecutará dentro de WebView.

Existen varios riesgos asociados con los puentes nativos:

  • Puentes basados en JavascriptInterface:
    • El método addJavascriptInterface inserta un objeto Java suministrado en cada fotograma de WebView, incluidos los iframes, lo que significa que es susceptible de ataque de terceros maliciosos que introduzcan marcos en un sitio web legítimo. Las aplicaciones orientadas al nivel de API 16 o versiones anteriores corren el riesgo de sufrir porque este método puede usarse para permitir que JavaScript controle el host y mantener la integridad de su aplicación.
    • Refleja el contenido que no es de confianza proporcionado por el usuario en WebViews nativas habilitadas con puente permite ataques de secuencias de comandos entre sitios (XSS).
  • Puentes basados en MessageChannel:
    • La falta de verificaciones de origen en los extremos de los canales de mensajes significa que se aceptarán mensajes de cualquier remitente, incluidos aquellos que contengan código malicioso.
    • Es posible exponer Java accidentalmente a JavaScript arbitrario.

Impacto

Los métodos addJavascriptInterface, postWebMessage y postMessage pueden ser que los agentes maliciosos aprovechan para acceder, manipular o inyectar el código que controlan en un componente WebView. Esto puede provocar que se redireccione a los usuarios a sitios maliciosos, cargar contenido malicioso o ejecutar un código malicioso en sus dispositivos que puede extraer datos sensibles o lograr la elevación de privilegios.

Riesgo: Riesgos de addJavascriptInterface

WebView implementa funciones básicas de un navegador, como el procesamiento de páginas, navegación y ejecución de JavaScript. WebView se puede usar dentro de una aplicación para mostrar contenido web como parte del diseño de una actividad. La implementación de un puente nativo dentro de un WebView con el método addJavascriptInterface puede crear problemas de seguridad, como la secuencia de comandos entre sitios (XSS), o permitir que los atacantes carguen contenido no confiable a través de la inyección de interfaz y manipulen la aplicación host de formas no deseadas, ejecutando código Java con los permisos de la aplicación host.

Mitigaciones

Inhabilita JavaScript

En situaciones en las que WebView no requiere JavaScript, no llames a setJavaScriptEnabled dentro de WebSettings (por ejemplo, mientras se muestra contenido HTML estático). De forma predeterminada, la ejecución de JavaScript está inhabilitada en WebView.

Quita la interfaz de JavaScript cuando se carga contenido que no es de confianza

Asegúrate de que se quiten los objetos de la interfaz de JavaScript llamando removeJavascriptInterface antes de que la WebView. Por ejemplo, esto puede hacerse en una llamada a shouldInterceptRequest

Kotlin

webView.removeJavascriptInterface("myObject")

Java

webView.removeJavascriptInterface("myObject");

Carga solo contenido web a través de HTTPS

Si necesitas cargar contenido que no sea de confianza, asegúrate de que WebView cargue contenido web en una conexión cifrada (consulta también nuestras pautas sobre texto sin cifrar) Comunicaciones). Evitar que la carga inicial de la página se realice en conexiones no encriptadas estableciendo android:usesCleartextTraffic en false en el archivo AndroidManifest o no permitir el tráfico HTTP en una seguridad de red config. Consulta la documentación de usesCleartextTraffic para obtener más información. información.

XML

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

Para garantizar que no se produzcan redireccionamientos y otras navegaciones en la app sin encriptar busca el esquema HTTP en loadUrl, o bien 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);
        }
    }
}

Valida el contenido que no sea de confianza

Si se cargan vínculos externos en un componente WebView, valida tanto el esquema como el host. (agregar dominios a la lista de entidades permitidas). El navegador predeterminado debe abrir los dominios que no estén en la lista de entidades permitidas.

No cargues contenido no confiable

Si es posible, carga solo el contenido y las URLs con permisos estrictos que pertenezcan al desarrollador de la app en WebView.

No expongas datos sensibles

Si tu aplicación accede a datos sensibles con una WebView, considera usar el método clearCache para borrar los archivos almacenados de forma local antes de usar la interfaz de JavaScript. También puedes usar encabezados del servidor, como no-store, para indican que una aplicación no debería almacenar en caché un contenido determinado.

No expongas funciones sensibles

Si tu aplicación requiere permisos sensibles o recopila datos sensibles, asegúrate de que se llame desde un código dentro de la aplicación y de que a los usuarios. Evita usar interfaces de JavaScript para cualquier operaciones sensibles o datos del usuario.

Orientación al nivel de API 21 o superior

Una forma segura de usar el método addJavascriptInterface es orientarlo al nivel de API 21 o superior. Para ello, asegúrate de que se llame al método solo cuando se ejecute en el nivel de API 21 o superior. Antes del nivel de API 21, JavaScript podía usar el reflejo para acceder al público campos de un objeto insertado.


Riesgo: Riesgos de MessageChannel

La falta de control de origen en postWebMessage() y postMessage() podría permitir que los atacantes intercepten mensajes o envíen mensajes a controladores nativos.

Mitigaciones

Cuando configures postWebMessage() o postMessage(), evita el uso de * como origen de destino y, en su lugar, especifica de forma explícita el dominio de envío esperado para permitir solo los mensajes de dominios de confianza.


Recursos