WebViews: inclusão de arquivos não seguros

Categoria do OWASP: MASVS-STORAGE - Armazenamento

Visão geral

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

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

  • WebSettings é uma classe que contém métodos que gerenciam os estados de configuração para WebViews. Esses métodos podem abrir WebViews para diferentes ataques que serão descritos mais adiante. Neste documento, vamos analisar os métodos relacionados ao acesso a arquivos e a configuração que permite a execução de JavaScript:
  • Os métodos setAllowFileAccess, setAllowFileAccessFromFileURLs e setAllowUniversalAccessFromFileURLs podem ser usados para conceder acesso a arquivos locais, usando um URL de esquema de arquivo (file://). No entanto, eles podem ser explorados por scripts maliciosos para acessar arquivos locais arbitrários aos quais o aplicativo tem acesso, como a própria pasta /data/. Por esse motivo, esses métodos foram sinalizados como não seguros e foram 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 em WebViews. Isso deixa os aplicativos vulneráveis a XSS baseado em arquivos. Principalmente 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 ficam 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 um WebView. No entanto, esse recurso pode ser abusado porque os WebViews não aplicam restrições sobre qual arquivo é selecionado.

Impacto

O impacto da inclusão de arquivos pode depender de quais WebSettings estão configuradas no 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 do app particulares. A ativação da execução de JavaScript pode permitir que invasores executem JavaScript em um 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 o WebView garantir que a origem do arquivo seja confiável.

Risco: acesso arriscado a arquivos por file://

A ativação de setAllowFileAccess, setAllowFileAccessFromFileURLs, e setAllowUniversalAccessFromFileURLs pode permitir que intents maliciosas e solicitações de WebView com um contexto file:// acessem arquivos locais arbitrários, incluindo cookies do WebView e dados particulares do app. Além disso, o uso do método onShowFileChooser pode permitir 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 file:// URLs, é importante permitir apenas URLs específicos que sejam legítimos, evitando erros comuns.

Usar 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 WebSettings perigosos

O valor do método setAllowFileAccess() é definido como TRUE por padrão no nível 29 da API e versões anteriores, e FALSE no nível 30 da API e versões mais recentes. Os métodos setAllowFileAccessFromFileURLs() e setAllowUniversalAccessFromFileURLs() são definidos como FALSE por padrão no nível 16 da API e versões mais recentes. Esses padrões foram alterados no nível 16 da API para aplicar uma segurança mais rigorosa, restringindo o acesso de mesma origem para arquivos locais, protegendo apps contra possíveis scripts em vários locais (XSS) e acesso não autorizado a arquivos.

Se houver necessidade de configurar outras WebSettings, é melhor desativar esses métodos explicitamente, especialmente para apps destinados a níveis de API menores ou iguais a 29.


Risco: XSS baseado em arquivos

Definir o método setJavacriptEnabled como TRUE permite que o JavaScript seja executado em um WebView e, 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 no WebView.

Mitigações

Impedir que 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 WebViews executem JavaScript

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

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

Às vezes, é necessário ativar essas configurações em 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 proibir JavaScript arbitrário é uma boa maneira de garantir que o conteúdo seja confiável. Caso contrário, impedir que o tráfego de texto não criptografado seja carregado garante que os WebViews com configurações perigosas não possam carregar URLs HTTP. Isso pode ser feito pelo manifesto, definindo android:usesCleartextTraffic como False, ou definindo uma Network Security Config que não permita tráfego HTTP.


Recursos