WebViews: inclusão de arquivos não seguros

Categoria do OWASP: MASVS-STORAGE - Armazenamento (link em inglês)

Visão geral

Este documento aborda vários problemas relacionados à inclusão de arquivos que têm mitigações semelhantes. Esses problemas se concentram em vulnerabilidades decorrentes do acesso a arquivos em WebViews e variam de WebSettings perigosos que permitem o acesso a arquivos ou a ativação do JavaScript a um método WebKit que cria uma solicitação de seleção de arquivos. Este documento pode ser útil se você estiver procurando orientações sobre como corrigir problemas na WebView decorrentes do uso do esquema file://, do acesso irrestrito a arquivos locais e do scripting em vários sites.

Mais especificamente, este documento aborda os seguintes tópicos:

  • WebSettings é uma classe que contém métodos que gerenciam os estados de configuração das WebViews. Esses métodos podem abrir WebViews para diferentes ataques, que serão descritos mais adiante. Neste documento, vamos analisar os métodos relacionados a como os arquivos podem ser acessados e a configuração que permite a execução do JavaScript:
  • Os métodos setAllowFileAccess, setAllowFileAccessFromFileURLs e setAllowUniversalAccessFromFileURLs podem ser usados para conceder acesso a arquivos locais usando um URL do esquema de arquivos (file://). No entanto, eles podem ser explorados por scripts maliciosos para acessar arquivos locais arbitrários a que o aplicativo tem acesso, como a própria pasta /data/. Por esse motivo, esses métodos foram sinalizados como não seguros e descontinuados na API 30 em favor de alternativas mais seguras, como WebViewAssetLoader.
  • O método setJavascriptEnabled pode ser usado para ativar a execução de JavaScript nas WebViews. Isso deixa os aplicativos vulneráveis a XSS baseado em arquivos. Especialmente quando configurado para permitir o carregamento de arquivos locais ou conteúdo da Web não confiável que pode conter código executável, configurado para permitir o acesso a arquivos que podem ser criados ou alterados por fontes externas ou permitir que WebViews executem JavaScript, os usuários e os dados deles são colocados em risco.
  • WebChromeClient.onShowFileChooser é um método pertencente ao pacote android.webkit, que fornece ferramentas de navegação na Web. Esse método pode ser usado para permitir que os usuários selecionem arquivos em uma WebView. No entanto, esse recurso pode ser usado indevidamente porque as WebViews não impõem restrições ao arquivo selecionado.

Impacto

O impacto da inclusão de arquivos pode depender de quais WebSettings são configuradas na WebView. Permissões de arquivo muito amplas podem permitir que invasores acessem arquivos locais e roubem dados sensíveis, PII (informações de identificação pessoal) ou dados privados do app. A ativação da execução do JavaScript pode permitir que invasores executem JavaScript em uma WebView ou no dispositivo de um usuário. Os arquivos selecionados usando o método onShowFileChooser podem comprometer a segurança do usuário, já que não há como o método ou a WebView garantir que a origem do arquivo seja confiável.

Risco: acesso arriscado a arquivos pelo file://

Ativar setAllowFileAccess, setAllowFileAccessFromFileURLs e setAllowUniversalAccessFromFileURLs pode permitir que intents maliciosas e solicitações da WebView com um contexto file:// acessem arquivos locais arbitrários, incluindo cookies da WebView e dados privados do app. Além disso, o uso do método onShowFileChooser permite que os usuários selecionem e façam o download de arquivos de fontes não confiáveis.

Esses métodos podem levar à exfiltração de PII, credenciais de login ou outros dados sensíveis, dependendo da configuração do aplicativo.

Mitigações

Validar URLs de arquivos

Se o app exigir acesso a arquivos por URLs file://, é importante permitir apenas URLs específicos conhecidos por serem legítimos, evitando erros comuns.

Usar o WebViewAssetLoader

Use WebViewAssetLoader em vez dos métodos mencionados. Esse método usa o esquema http(s)//: em vez de um esquema file:// para acessar recursos do sistema de arquivos local e não é vulnerável ao 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");

Desativar métodos perigosos do WebSettings

Os valores dos métodos setAllowFileAccess(), setAllowFileAccessFromFileURLs() e setAllowUniversalAccessFromFileURLs() são definidos como TRUE por padrão no nível 29 da API e anteriores, e FALSE no nível 30 da API e mais recentes.

Se for necessário configurar outros WebSettings, é melhor desativá-los explicitamente, especialmente para apps com nível de API igual ou inferior a 29.


Risco: XSS baseado em arquivos

A definição do método setJavacriptEnabled como TRUE permite que o JavaScript seja executado em um WebView. Em combinação com o acesso a arquivos ativado, conforme descrito anteriormente, o XSS baseado em arquivos é possível pela execução de código em arquivos arbitrários ou sites maliciosos abertos na WebView.

Mitigações

Impedir que os WebViews carreguem arquivos locais

Assim como no risco anterior, o XSS baseado em arquivos pode ser evitado se setAllowFileAccess(), setAllowFileAccessFromFileURLs() e setAllowUniversalAccessFromFileURLs() forem definidos como FALSE.

Impedir que as WebViews executem JavaScript

Defina o método setJavascriptEnabled como FALSE para que o JavaScript não possa ser executado nas WebViews.

Impedir que os WebViews carreguem conteúdo não confiável

Às vezes, é necessário ativar essas configurações nas WebViews. Nesse caso, é importante garantir que apenas conteúdo confiável seja carregado. Limitar a execução de JavaScript apenas ao que você controla e não permitir JavaScript arbitrário é uma boa maneira de garantir a confiabilidade do conteúdo. Caso contrário, impedir o carregamento de tráfego de texto não criptografado garante que as WebViews com configurações perigosas não consigam carregar URLs HTTP. Isso pode ser feito no manifesto, definindo android:usesCleartextTraffic como False, ou definindo um Network Security Config que proíbe o tráfego HTTP.


Recursos