WebViews: Inclusión de archivos no seguros

Categoría de OWASP: MASVS-STORAGE: Almacenamiento

Descripción general

En este documento, se abarcan varios problemas relacionados con la inclusión de archivos que comparten mitigaciones similares. Estos problemas se centran en las vulnerabilidades derivadas del acceso a archivos dentro de WebViews y abarcan desde WebSettings peligrosas que permiten el acceso a archivos o habilitan JavaScript hasta un método de 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 del uso del esquema file://, el acceso sin restricciones a archivos locales y las secuencias de comandos entre sitios.

De manera más concreta, en este documento, se abarcan 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 relacionados con la forma en que se puede acceder a los archivos y la configuración que permite ejecutar JavaScript:
  • Los métodos setAllowFileAccess, setAllowFileAccessFromFileURLs y setAllowUniversalAccessFromFileURLs se pueden usar para otorgar acceso a archivos locales con una URL de esquema de archivo (file://). Sin embargo, las secuencias de comandos maliciosas pueden aprovecharlos para acceder a archivos locales arbitrarios a los que la aplicación tiene acceso, como su propia carpeta /data/. Por este motivo, estos métodos se marcaron como inseguros y quedaron obsoletos en la 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 basadas en archivos. En especial, cuando se configura para permitir la carga de archivos locales o contenido web que no es de confianza que puede contener código ejecutable, configurado para permitir el acceso a archivos que pueden crear o cambiar fuentes externas, o permitir que WebViews ejecute JavaScript, los usuarios y sus datos corren 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 una WebView. Sin embargo, esta función se puede usar de forma inadecuada porque WebViews no aplica restricciones sobre qué archivo se selecciona.

Impacto

El impacto de la inclusión de archivos puede depender de qué WebSettings se configuren en WebView. Los permisos de archivo demasiado amplios pueden permitir que los atacantes accedan a archivos locales y roben datos sensibles, PII (información de identificación personal) o datos de app privados. 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 garanticen que la fuente del archivo sea de confianza.

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

Habilitar setAllowFileAccess, setAllowFileAccessFromFileURLs, y setAllowUniversalAccessFromFileURLs puede 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, usar el método onShowFileChooser puede permitir que los usuarios seleccionen y descarguen archivos de fuentes que no son de confianza.

Todos estos métodos pueden provocar la filtración de PII, credenciales de acceso o cualquier otro dato sensible, 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 file:// URLs, es importante permitir solo URLs específicas que se sepa que son legítimas y 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 local 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

Los valores de los métodos setAllowFileAccess(), setAllowFileAccessFromFileURLs() y setAllowUniversalAccessFromFileURLs() se establecen de forma predeterminada 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 otros WebSettings, lo mejor sería inhabilitar estos métodos explícitamente, en especial para las apps orientadas a niveles de API menores o iguales a 29.


Riesgo: XSS basado en archivos

Si se establece el método setJavacriptEnabled en TRUE, se permite que se ejecute JavaScript dentro de una WebView y, en combinación con el acceso a archivos habilitado como se describió anteriormente, es posible usar XSS basado en archivos mediante la ejecución de código dentro de archivos arbitrarios o sitios web maliciosos abiertos dentro de la WebView.

Mitigaciones

Impide que WebViews cargue archivos locales

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

Impide que WebViews ejecute JavaScript

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

Asegúrate de que WebViews no cargue contenido que no sea de confianza

A veces, es necesario habilitar esta configuración dentro de 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, impedir que se cargue el tráfico de texto sin formato garantiza que WebViews con configuración peligrosa al menos no pueda cargar URLs HTTP. Esto se puede hacer a través del manifiesto, estableciendo android:usesCleartextTraffic en False, o estableciendo una Network Security Config que no permita el tráfico HTTP.


Recursos