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

Категория OWASP: MASVS-STORAGE: Хранение

Обзор

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

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

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

Влияние

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

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

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

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

Смягчение последствий

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

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

Использовать WebViewAssetLoader

Используйте WebViewAssetLoader вместо упомянутых методов. Этот метод использует схему http(s)//: вместо file:// для доступа к ресурсам локальной файловой системы и не подвержен описанной атаке.

Котлин

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

Ява

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() , setAllowFileAccessFromFileURLs() и setAllowUniversalAccessFromFileURLs() по умолчанию установлены в TRUE на уровне API 29 и ниже и в FALSE на уровне API 30 и выше.

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


Риск: XSS-атака на основе файлов

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

Смягчение последствий

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

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

Запретить WebViews выполнять JavaScript

Установите метод setJavascriptEnabled в FALSE , чтобы JavaScript не мог выполняться в WebViews.

Убедитесь, что WebViews не загружают ненадежный контент

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


Ресурсы