WebViews: Inclusión de archivos no seguros

Categoría de OWASP: MASVS-STORAGE: Almacenamiento

Descripción general

En este documento, se abordan varios problemas relacionados con la inclusión de archivos que comparten mitigaciones similares. Estos problemas se centran en las vulnerabilidades que surgen del acceso a archivos dentro de WebViews y van desde un WebSettings peligroso que permite el acceso a archivos o habilita JavaScript hasta un método WebKit que crea una solicitud de selección de archivos. Este documento debería ser útil si buscas orientación para solucionar problemas en WebView que surgen por el uso del esquema file://, el acceso sin restricciones a archivos locales y la ejecución de secuencias de comandos entre sitios.

Más concretamente, en este documento, se abordan los siguientes temas:

  • WebSettings es una clase que contiene métodos que administran los estados de configuración de WebViews. Estos métodos pueden abrir WebViews a diferentes ataques, que se describirán más adelante. En este documento, analizaremos los métodos que se relacionan con la forma en que se puede acceder a los archivos y la configuración que permite que se ejecute JavaScript:
  • Los métodos setAllowFileAccess, setAllowFileAccessFromFileURLs y setAllowUniversalAccessFromFileURLs se pueden usar para otorgar acceso a archivos locales mediante una URL de esquema de archivo (file://). Sin embargo, las secuencias de comandos maliciosas pueden aprovecharlas para acceder a archivos locales arbitrarios a los que tiene acceso la aplicación, como su propia carpeta /data/. Por este motivo, estos métodos se marcaron como no seguros y dejaron de estar disponibles en el nivel de API 30 en favor de alternativas más seguras, como WebViewAssetLoader.
  • El método setJavascriptEnabled se puede usar para habilitar la ejecución de JavaScript dentro de WebViews. Esto deja a las aplicaciones vulnerables a XSS basado en archivos. Esto es especialmente cierto cuando se configuran para permitir la carga de archivos locales o contenido web no confiable que puede contener código ejecutable, para permitir el acceso a archivos que pueden crear o cambiar fuentes externas, o para permitir que WebViews ejecute JavaScript. En estos casos, los usuarios y sus datos están en riesgo.
  • WebChromeClient.onShowFileChooser es un método que pertenece al paquete android.webkit, que proporciona herramientas de navegación web. Este método se puede usar para permitir que los usuarios seleccionen archivos dentro de un WebView. Sin embargo, se puede hacer un uso inadecuado de esta función porque WebViews no aplican restricciones sobre el archivo que se selecciona.

Impacto

El impacto de la inclusión de archivos puede depender de los WebSettings que se configuren en WebView. Los permisos de archivos demasiado amplios pueden permitir que los atacantes accedan a archivos locales y roben datos sensibles, PII (información de identificación personal) o datos privados de la app. Habilitar la ejecución de JavaScript puede permitir que los atacantes ejecuten JavaScript dentro de una WebView o en el dispositivo de un usuario. Los archivos seleccionados con el método onShowFileChooser podrían poner en riesgo la seguridad del usuario, ya que no hay forma de que el método o WebView se aseguren de que la fuente del archivo sea de confianza.

Riesgo: Acceso riesgoso a archivos a través de file://

Si habilitas setAllowFileAccess, setAllowFileAccessFromFileURLs y setAllowUniversalAccessFromFileURLs, puedes permitir que intents maliciosos y solicitudes de WebView con un contexto file:// accedan a archivos locales arbitrarios, incluidas las cookies de WebView y los datos privados de la app. Además, el uso del método onShowFileChooser puede permitir que los usuarios seleccionen y descarguen archivos de fuentes no confiables.

Todos estos métodos pueden llevar a la exfiltración de PII, credenciales de acceso o otros datos sensibles, según la configuración de la aplicación.

Mitigaciones

Valida las URLs de los archivos

Si tu app requiere acceso a archivos a través de URLs de file://, es importante que solo incluyas en la lista de entidades permitidas URLs específicas que se sepa que son legítimas, lo que evitará errores comunes.

Usa WebViewAssetLoader

Usa WebViewAssetLoader en lugar de los métodos mencionados. Este método usa el esquema http(s)//: en lugar de un esquema file:// para acceder a los recursos del sistema de archivos locales y no es vulnerable al ataque descrito.

Kotlin

val assetLoader: WebViewAssetLoader = Builder()
  .addPathHandler("/assets/", AssetsPathHandler(this))
  .build()

webView.setWebViewClient(object : WebViewClientCompat() {
  @RequiresApi(21)
  override fun shouldInterceptRequest(view: WebView?, request: WebResourceRequest): WebResourceResponse {
    return assetLoader.shouldInterceptRequest(request.url)
  }

  @Suppress("deprecation") // for API < 21
  override fun shouldInterceptRequest(view: WebView?, url: String?): WebResourceResponse {
    return assetLoader.shouldInterceptRequest(Uri.parse(url))
  }
})

val webViewSettings: WebSettings = webView.getSettings()
// Setting this off for security. Off by default for SDK versions >= 16.
webViewSettings.allowFileAccessFromFileURLs = false
// Off by default, deprecated for SDK versions >= 30.
webViewSettings.allowUniversalAccessFromFileURLs = false
// Keeping these off is less critical but still a good idea, especially if your app is not
// using file:// or content:// URLs.
webViewSettings.allowFileAccess = false
webViewSettings.allowContentAccess = false

// Assets are hosted under http(s)://appassets.androidplatform.net/assets/... .
// If the application's assets are in the "main/assets" folder this will read the file
// from "main/assets/www/index.html" and load it as if it were hosted on:
// https://appassets.androidplatform.net/assets/www/index.html
webView.loadUrl("https://appassets.androidplatform.net/assets/www/index.html")

Java

final WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
         .addPathHandler("/assets/", new AssetsPathHandler(this))
         .build();

webView.setWebViewClient(new WebViewClientCompat() {
    @Override
    @RequiresApi(21)
    public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
        return assetLoader.shouldInterceptRequest(request.getUrl());
    }

    @Override
    @SuppressWarnings("deprecation") // for API < 21
    public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
        return assetLoader.shouldInterceptRequest(Uri.parse(url));
    }
});

WebSettings webViewSettings = webView.getSettings();
// Setting this off for security. Off by default for SDK versions >= 16.
webViewSettings.setAllowFileAccessFromFileURLs(false);
// Off by default, deprecated for SDK versions >= 30.
webViewSettings.setAllowUniversalAccessFromFileURLs(false);
// Keeping these off is less critical but still a good idea, especially if your app is not
// using file:// or content:// URLs.
webViewSettings.setAllowFileAccess(false);
webViewSettings.setAllowContentAccess(false);

// Assets are hosted under http(s)://appassets.androidplatform.net/assets/... .
// If the application's assets are in the "main/assets" folder this will read the file
// from "main/assets/www/index.html" and load it as if it were hosted on:
// https://appassets.androidplatform.net/assets/www/index.html
webview.loadUrl("https://appassets.androidplatform.net/assets/www/index.html");

Inhabilita los métodos peligrosos de WebSettings

De forma predeterminada, los valores de los métodos setAllowFileAccess(), setAllowFileAccessFromFileURLs() y setAllowUniversalAccessFromFileURLs() se establecen en TRUE en el nivel de API 29 y versiones anteriores, y en FALSE en el nivel de API 30 y versiones posteriores.

Si es necesario configurar otro WebSettings, lo mejor es inhabilitar estos métodos de forma explícita, en especial para las apps orientadas a niveles de API inferiores o iguales a 29.


Riesgo: XSS basado en archivos

Si estableces el método setJavacriptEnabled en TRUE, se permite que JavaScript se ejecute dentro de un WebView y, en combinación con el acceso a archivos habilitado como se describió anteriormente, es posible realizar un XSS basado en archivos a través de la ejecución de código dentro de archivos arbitrarios o sitios web maliciosos que se abren dentro de WebView.

Mitigaciones

Evita que WebView cargue archivos locales

Al igual que con el riesgo anterior, se puede evitar el XSS basado en archivos si setAllowFileAccess(), setAllowFileAccessFromFileURLs() y setAllowUniversalAccessFromFileURLs() se configuran en FALSE.

Evita que WebViews ejecute JavaScript

Establece el método setJavascriptEnabled en FALSE para que JavaScript no se pueda ejecutar en WebViews.

Asegúrate de que las WebViews no carguen contenido que no sea de confianza

A veces, es necesario habilitar esta configuración en WebViews. En este caso, es importante asegurarse de que solo se cargue contenido de confianza. Limitar la ejecución de JavaScript solo a lo que controlas y no permitir JavaScript arbitrario es una buena manera de garantizar que el contenido sea confiable. De lo contrario, evitar que se cargue el tráfico de texto simple garantiza que los WebViews con parámetros de configuración peligrosos, al menos, no puedan cargar URLs HTTP. Esto se puede hacer a través del manifiesto, configurando android:usesCleartextTraffic como False o configurando un Network Security Config que no permita el tráfico HTTP.


Recursos