Перейти к содержанию

Опасная комбинация настроек WebView: JavaScript и доступ к локальным файлам

Критичность: ВЫСОКИЙ
Способ обнаружения: DAST, WEBVIEW

Описание

Дефект возникает, когда в WebView одновременно включены исполнение JavaScript и доступ к локальной файловой системе. Опасную комбинацию образуют флаги:

  • setJavaScriptEnabled(true) — исполнение JavaScript;
  • setAllowFileAccess(true) — доступ к схеме file://;
  • setAllowFileAccessFromFileURLs(true) — страница, открытая по file://, может читать другие файлы по file://;
  • setAllowUniversalAccessFromFileURLs(true) — страница, открытая по file://, может обращаться к контенту любого источника (обход Same-Origin Policy).

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

Пример небезопасного кода:

WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setAllowFileAccess(true);
settings.setAllowFileAccessFromFileURLs(true);
settings.setAllowUniversalAccessFromFileURLs(true);
webView.loadUrl(externalUrl); // при подгрузке постороннего контента — критично

Проблема

  1. Чтение приватных файлов приложения. JavaScript может прочитать файлы песочницы (/data/data/<pkg>/...): SQLite-базы, токены, настройки — и эксфильтровать их.
  2. Обход Same-Origin Policy. setAllowUniversalAccessFromFileURLs(true) снимает изоляцию источников, позволяя локальной странице обращаться к произвольным ресурсам, включая удалённые.
  3. Усиление XSS. При наличии XSS в загруженном контенте указанная комбинация превращает межсайтовый скриптинг в кражу локальных данных.
  4. Эксплуатация через сторонний file://. Если злоумышленник может подсунуть в WebView file://-URL (например, через экспортируемый компонент или скачанный HTML), он исполнит свой скрипт с правами доступа к файлам приложения.

Рекомендации

  1. Отключите доступ к файловой системе для веб-контента. Это основная мера; задавайте флаги явно (дефолты зависят от версии API: setAllowFileAccessFromFileURLs/setAllowUniversalAccessFromFileURLsfalse начиная с API 16; setAllowFileAccessfalse лишь при targetSdkVersion ≥ 30, иначе true; полагаться на дефолты не следует):

    settings.setAllowFileAccess(false);
    settings.setAllowFileAccessFromFileURLs(false);
    settings.setAllowUniversalAccessFromFileURLs(false);
    settings.setAllowContentAccess(false);
    

  2. Никогда не сочетайте setJavaScriptEnabled(true) с доступом к file:// при загрузке недоверенного или удалённого контента. AllowUniversalAccessFromFileURLs(true) не должен использоваться в production ни при каких условиях.

  3. Отдавайте локальные ресурсы через WebViewAssetLoader. Он обслуживает упакованные файлы и контент через виртуальный https-домен appassets.androidplatform.net, сохраняя Same-Origin Policy и не открывая доступ к произвольным file://:

    WebViewAssetLoader loader = new WebViewAssetLoader.Builder()
        .addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this))
        .addPathHandler("/res/",    new WebViewAssetLoader.ResourcesPathHandler(this))
        .build();
    webView.setWebViewClient(new WebViewClientCompat() {
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView v, WebResourceRequest req) {
            return loader.shouldInterceptRequest(req.getUrl());
        }
    });
    webView.loadUrl("https://appassets.androidplatform.net/assets/index.html");
    

  4. Изолируйте сценарии, где file:// действительно необходим. Используйте для них отдельный экземпляр WebView с выключенным JavaScript и без сетевого доступа; не смешивайте локальный и удалённый контент в одном WebView.

  5. Контролируйте загружаемый путь. Если путь к файлу формируется динамически — канонизируйте его и проверяйте, что он находится внутри разрешённого каталога (защита от Path Traversal). Запрещайте file://-URL, пришедшие из внешних источников (Intent, deeplink).

  6. Не храните секреты в файлах, доступных WebView. Чувствительные данные держите в защищённых хранилищах (EncryptedSharedPreferences, Android Keystore), а не в файлах, которые может прочитать веб-контент.

  7. Усильте защиту на стороне страницы. Для подконтрольного контента задавайте Content-Security-Policy и запрещайте загрузку внешних ресурсов, чтобы ограничить последствия возможной инъекции.

Ссылки

  1. https://developer.android.com/privacy-and-security/risks/webview-unsafe-file-inclusion
  2. https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader
  3. https://developer.android.com/reference/android/webkit/WebSettings#setAllowUniversalAccessFromFileURLs(boolean)
  4. https://mas.owasp.org/MASTG/tests/android/MASVS-PLATFORM/MASTG-TEST-0033/
  5. https://cwe.mitre.org/data/definitions/749.html
  6. https://cwe.mitre.org/data/definitions/200.html
  7. https://cwe.mitre.org/data/definitions/79.html
  8. https://cwe.mitre.org/data/definitions/22.html
К началу