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

Потенциально опасные настройки WebView

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

Описание

WebView — это компонент Android, который позволяет встраивать веб-контент непосредственно в интерфейс приложения. Его поведение управляется объектом WebSettings, который включает десятки флагов. Часть из них расширяет возможности загружаемого веб-контента (исполнение JavaScript, доступ к файловой системе, кеширование, доступ к содержимому через content://, смешанный HTTP/HTTPS-контент). Stingray фиксирует факт включения таких настроек как информационную находку: сама по себе настройка не является уязвимостью, но требует ручной проверки в контексте того, какой контент загружается в WebView.

Пример конфигурации, попадающей под наблюдение:

WebView webView = findViewById(R.id.webview);
WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
settings.setAllowContentAccess(true);

Проблема

Расширенные настройки WebView становятся уязвимостью, когда в компонент попадает недоверенный контент:

  1. Исполнение постороннего кода — при включённом JavaScript загрузка непроверенного контента открывает путь к XSS и эксплуатации JavaScript-мостов.
  2. Доступ к данным приложения — настройки доступа к файлам и content:// могут позволить веб-странице обращаться к ресурсам песочницы приложения.
  3. Накопление чувствительных данных — кеш, DOM Storage, cookies и база данных WebView могут сохранять конфиденциальную информацию в открытом виде.
  4. Понижение защиты канала — разрешённый смешанный контент (MIXED_CONTENT_ALWAYS_ALLOW) позволяет подгружать ресурсы по HTTP на HTTPS-странице, что открывает MITM.

Информационный характер находки означает, что окончательная оценка риска требует анализа источника загружаемого контента и совокупности включённых настроек. Ниже приведён полный набор мер по приведению WebView к безопасной конфигурации — применяйте те, что соответствуют сценарию.

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

  1. Включайте только необходимый минимум возможностей. Если функциональность не требует JavaScript — оставьте его выключенным (setJavaScriptEnabled(false) — значение по умолчанию). Каждый включённый флаг расширяет поверхность атаки, поэтому исходите из принципа «запрещено всё, что явно не разрешено».

  2. Отключите доступ WebView к файловой системе, если он не нужен. Дефолты зависят от версии API: setAllowFileAccessFromFileURLs/setAllowUniversalAccessFromFileURLsfalse начиная с API 16; setAllowFileAccesstrue по умолчанию и становится false лишь при targetSdkVersion ≥ 30 (Android 11). Полагаться на дефолты не стоит — выставляйте флаги явно:

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

  3. Загружайте локальные ресурсы через WebViewAssetLoader, а не по схеме file://. Загрузчик отдаёт упакованные ассеты через виртуальный https-домен, сохраняя изоляцию источников (Same-Origin Policy):

    WebViewAssetLoader assetLoader = new WebViewAssetLoader.Builder()
        .addPathHandler("/assets/", new WebViewAssetLoader.AssetsPathHandler(this))
        .build();
    webView.setWebViewClient(new WebViewClientCompat() {
        @Override
        public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
            return assetLoader.shouldInterceptRequest(request.getUrl());
        }
    });
    

  4. Запретите смешанный контент на HTTPS-страницах:

    settings.setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW);
    

  5. Ограничьте навигацию доверенными доменами. Реализуйте WebViewClient.shouldOverrideUrlLoading() с allow-list разрешённых схем и хостов; запрещайте javascript:, file:, data:, content: и неизвестные схемы. Не передавайте внешние ссылки на открытие «как есть».

  6. Загружайте контент только по HTTPS и не игнорируйте TLS-ошибки. В onReceivedSslError() всегда вызывайте handler.cancel(), никогда — handler.proceed().

  7. Минимизируйте JavaScript-мосты. Не используйте addJavascriptInterface() для недоверенного контента. Если нужен канал native↔web — применяйте WebViewCompat.addWebMessageListener() с явным списком разрешённых источников (allowedOriginRules) вместо @JavascriptInterface.

  8. Включите Google Safe Browsing для защиты от вредоносных и фишинговых страниц:

    <manifest>
      <application>
        <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
                   android:value="true"/>
      </application>
    </manifest>
    

  9. Управляйте чувствительными данными WebView. Отключайте кеширование секретных страниц и очищайте состояние при выходе из чувствительных сценариев:

    webView.clearCache(true);
    webView.clearFormData();
    WebStorage.getInstance().deleteAllData();
    CookieManager.getInstance().removeAllCookies(null);
    
    Также отключите хранение паролей/форм (setSavePassword(false), setSaveFormData(false) на старых API) и сторонние cookies (CookieManager.setAcceptThirdPartyCookies(webView, false)).

  10. Поддерживайте System WebView в актуальном состоянии. Уязвимости движка закрываются обновлением системного WebView; для доступа к новым механизмам безопасности на старых API используйте библиотеку androidx.webkit.

  11. Применяйте защиту на стороне контента. Для страниц под вашим контролем задавайте строгую политику Content-Security-Policy, ограничивающую источники скриптов и ресурсов, — это снижает последствия возможного XSS.

Ссылки

  1. https://developer.android.com/develop/ui/views/layout/webapps/webview
  2. https://developer.android.com/reference/android/webkit/WebSettings
  3. https://developer.android.com/reference/androidx/webkit/WebViewAssetLoader
  4. https://developer.android.com/develop/ui/views/layout/webapps/managing-webview
  5. https://developer.android.com/privacy-and-security/risks/insecure-webview-mixed-content
  6. https://mas.owasp.org/MASTG/tests/android/MASVS-PLATFORM/MASTG-TEST-0033/
  7. https://cwe.mitre.org/data/definitions/200.html
  8. https://cwe.mitre.org/data/definitions/79.html
К началу