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