Категория 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-трафик.
Ресурсы
- Справочная страница API setAllowUniversalAccessFromFileURLs
- Справочная страница API setAllowFileAccessFromFileURLs
- Справочная страница API WebViewAssetLoader
- Документация CodeQL
- Сверхзащищенный блог
- справочная страница onShowFileChooser
