WebView: небезопасное включение файлов

Категория OWASP: MASVS-STORAGE: Storage.

Обзор

В этом документе рассматривается несколько проблем, связанных с включением файлов, которые имеют схожие способы устранения. Эти проблемы связаны с уязвимостями, возникающими при доступе к файлам в WebView, и варьируются от опасных WebSettings, разрешающих доступ к файлам или включающих JavaScript, до метода WebKit, который создает запрос на выбор файла. Этот документ поможет вам устранить проблемы в WebView, связанные с использованием схемы file://, неограниченным доступом к локальным файлам и межсайтовым скриптингом.

В частности, в этом документе рассматриваются следующие темы:

  • WebSettings – класс, содержащий методы, которые управляют состояниями настроек для компонентов WebView. Эти методы могут сделать компоненты WebView уязвимыми для различных атак, которые будут описаны ниже. В этом документе мы рассмотрим методы, которые относятся к способам доступа к файлам, и настройку, которая позволяет выполнять JavaScript:
  • Методы setAllowFileAccess, setAllowFileAccessFromFileURLs и setAllowUniversalAccessFromFileURLs можно использовать, чтобы предоставлять доступ к локальным файлам с помощью URL-адреса схемы файла (file://). Однако вредоносные скрипты могут использовать эти методы, чтобы получать доступ к произвольным локальным файлам, к которым у приложения есть доступ, например к собственной папке /data/. Поэтому эти методы были помечены как небезопасные и в API 30 заменены более безопасными альтернативами, такими как WebViewAssetLoader.
  • Чтобы разрешить выполнение JavaScript в WebView, можно использовать метод setJavascriptEnabled. Это делает приложения уязвимыми к межсайтовому скриптингу на основе файлов. Если WebView может загружать локальные файлы или ненадежный веб-контент, который может содержать исполняемый код, или если у WebView есть доступ к файлам, которые могут быть созданы или изменены внешними источниками, или если WebView может выполнять код JavaScript, пользователи и их данные подвергаются риску.
  • WebChromeClient.onShowFileChooser – это метод, принадлежащий пакету android.webkit, который предоставляет инструменты для просмотра веб-страниц. Этот метод позволяет пользователям выбирать файлы в WebView. Однако этой функцией можно злоупотребить, поскольку WebView не накладывает ограничений на выбор файлов.

Влияние

Последствия внедрения файлов могут зависеть от того, какие настройки WebSettings заданы в WebView. Слишком широкие разрешения файлов могут позволить злоумышленникам получить доступ к локальным файлам и украсть конфиденциальные данные, информацию, позволяющую идентифицировать личность, или личные данные приложения. Если выполнение JavaScript разрешено, злоумышленники могут запускать код JavaScript в компоненте WebView или на устройстве пользователя. Файлы, выбранные с помощью метода onShowFileChooser, могут поставить под угрозу безопасность пользователя, поскольку ни метод, ни WebView не могут гарантировать, что источник файла надежен.

Риск: небезопасный доступ к файлам через file://

Если включить setAllowFileAccess, setAllowFileAccessFromFileURLs и setAllowUniversalAccessFromFileURLs, вредоносные объекты Intent и запросы WebView с контекстом file:// могут получить доступ к произвольным локальным файлам, включая файлы cookie WebView и личные данные приложения. Кроме того, метод onShowFileChooser позволяет пользователям выбирать и скачивать файлы из ненадежных источников.

Все эти методы могут привести к краже информации, позволяющей идентифицировать личность, учетных данных или другой конфиденциальной информации в зависимости от конфигурации приложения.

Предотвращение атак

Проверить URL файлов

Если вашему приложению требуется доступ к файлам через URL-адреса file://, важно добавлять в белый список только определенные URL, которые считаются допустимыми, избегая распространенных ошибок.

Используйте WebViewAssetLoader

Вместо указанных методов используйте WebViewAssetLoader. В этом методе для доступа к объектам локальной файловой системы используется схема http(s)//: вместо file://, поэтому он не уязвим для описанной атаки.

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");

Отключите опасные методы WebSettings

По умолчанию для метода setAllowFileAccess() задано значение TRUE на уровне API 29 и ниже и FALSE на уровне API 30 и выше. Методы setAllowFileAccessFromFileURLs() и setAllowUniversalAccessFromFileURLs() по умолчанию имеют значение FALSE в уровне API 16 и выше. (Эти настройки по умолчанию были изменены в уровне API 16, чтобы обеспечить более строгую безопасность за счет ограничения доступа к локальным файлам из одного источника, защищая приложения от потенциального межсайтового скриптинга (XSS) и несанкционированного доступа к файлам.)

Если вам нужно настроить другие WebSettings, лучше всего явно отключить эти методы, особенно для приложений с целевым уровнем API 29 или ниже.


Риск: межсайтовый скриптинг на основе файлов

Если для метода setJavacriptEnabled задано значение TRUE, то в WebView можно выполнять код JavaScript. В сочетании с доступом к файлам, как описано выше, это позволяет проводить XSS-атаки на основе файлов, выполняя код в произвольных файлах или на вредоносных сайтах, открытых в WebView.

Предотвращение атак

Запретите WebView загружать локальные файлы

Как и в предыдущем случае, межсайтового скриптинга на основе файлов можно избежать, если для параметров setAllowFileAccess(), setAllowFileAccessFromFileURLs() и setAllowUniversalAccessFromFileURLs() задано значение FALSE.

Запретите WebView выполнять код JavaScript

Задайте для метода setJavascriptEnabled значение FALSE, чтобы код JavaScript не мог выполняться в компонентах WebView.

Исключите загрузку ненадежного контента WebView

Иногда эти настройки необходимо включить в WebView. В этом случае важно убедиться, что загружается только надежный контент. Ограничение выполнения JavaScript только тем, что вы контролируете, и запрет произвольного JavaScript – хороший способ обеспечить надежность контента. В противном случае запрет на загрузку незашифрованного трафика гарантирует, что компоненты WebView с опасными настройками не смогут загружать URL по протоколу HTTP. Это можно сделать в манифесте, задав для атрибута android:usesCleartextTraffic значение False, или настроив конфигурацию Network Security Config, запрещающую загружать данные по протоколу HTTP.


Ресурсы