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

Проброс произвольных данных в контекст WebView

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

Описание

Дефект возникает, когда данные из недоверенного источника (Intent, deeplink, файл, сетевой ответ, межпроцессное взаимодействие) попадают в WebView без валидации — через методы загрузки и исполнения: loadUrl, loadData, loadDataWithBaseURL, evaluateJavascript или через @JavascriptInterface-мост. Stingray перехватывает аргументы этих методов в рантайме и фиксирует попадание в них контролируемых извне значений.

Пример уязвимого кода:

// адрес и/или данные приходят из внешнего Intent
String url = getIntent().getStringExtra("target_url");
webView.loadUrl(url);                              // открытие произвольного URL

String html = getIntent().getStringExtra("html");
webView.loadData(html, "text/html", "UTF-8");      // рендеринг произвольного HTML/JS

Особенно опасно, когда такой WebView находится в экспортируемом компоненте: любой сторонний процесс может прислать Intent и заставить приложение открыть подконтрольную страницу.

Проблема

  1. Открытие произвольного URL. Контролируемый извне адрес позволяет загрузить подконтрольную злоумышленнику страницу — для фишинга от имени приложения или эксплуатации JavaScript-мостов.
  2. Инъекция HTML/JavaScript. Передача произвольного HTML в loadData/loadDataWithBaseURL/evaluateJavascript ведёт к исполнению постороннего JavaScript в контексте приложения (XSS).
  3. Кража данных и вызов нативных методов. В связке с @JavascriptInterface инъекция позволяет вызывать нативный код и выводить наружу данные приложения.
  4. Обход бизнес-логики и Same-Origin. Подмена baseURL в loadDataWithBaseURL меняет контекст происхождения страницы и может обойти клиентские проверки, а также получить доступ к данным «доверенного» домена.
  5. Опасные схемы. Передача javascript:, file:, data:, content: URL открывает исполнение кода или доступ к локальным ресурсам.

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

  1. Считайте недоверенным любой внешний ввод. Данные из Intent, deeplink, IPC, файлов и сети должны проходить валидацию до передачи в loadUrl/loadData/loadDataWithBaseURL/evaluateJavascript.

  2. Применяйте allow-list для адресов. Проверяйте схему и хост по белому списку; разрешайте только https и доверенные домены, отклоняйте javascript:, file:, data:, content: и неизвестные схемы:

    private static final Set<String> ALLOWED_HOSTS = Set.of("app.example.com");
    boolean isAllowed(String raw) {
        try {
            Uri u = Uri.parse(raw);
            return "https".equals(u.getScheme()) && ALLOWED_HOSTS.contains(u.getHost());
        } catch (Exception e) { return false; }
    }
    

  3. Ограничьте навигацию внутри WebView. Реализуйте WebViewClient.shouldOverrideUrlLoading()shouldInterceptRequest()), пропуская только разрешённые URL, а остальные — открывая во внешнем браузере или блокируя.

  4. Не экспортируйте компоненты с WebView без необходимости. Для Activity/Service, открывающих WebView по данным из Intent, задавайте android:exported="false" либо защиту permission уровня signature; проверяйте вызывающую сторону.

  5. Не передавайте недоверенный HTML. Формируйте разметку из доверенных шаблонов на стороне приложения и экранируйте подставляемые значения. В loadDataWithBaseURL используйте безопасный baseURL и корректную кодировку; не задавайте baseURL доверенного домена для недоверенного контента.

  6. Передавайте данные безопасно. Для канала native↔web используйте WebMessagePort/postWebMessage() и WebViewCompat.addWebMessageListener() с allowedOriginRules; при необходимости подставить значение в скрипт — экранируйте через JSONObject.quote() (не склейкой строк).

  7. Минимизируйте JavaScript-мосты и не выставляйте чувствительные методы через @JavascriptInterface.

  8. Не отключайте проверку TLS. В onReceivedSslError() вызывайте handler.cancel(). Запретите смешанный контент: setMixedContentMode(MIXED_CONTENT_NEVER_ALLOW).

  9. Усильте защиту контента. Включите Google Safe Browsing и задавайте строгий Content-Security-Policy для подконтрольных страниц, чтобы ограничить последствия инъекции.

Ссылки

  1. https://developer.android.com/develop/ui/views/layout/webapps/webview
  2. https://developer.android.com/privacy-and-security/risks/webview-unsafe-javascript-interface
  3. https://developer.android.com/reference/androidx/webkit/WebViewCompat
  4. https://developer.android.com/privacy-and-security/risks/unsafe-uri-loading
  5. https://mas.owasp.org/MASTG/tests/android/MASVS-PLATFORM/MASTG-TEST-0033/
  6. https://cwe.mitre.org/data/definitions/601.html
  7. https://cwe.mitre.org/data/definitions/79.html
  8. https://cwe.mitre.org/data/definitions/749.html
  9. https://cwe.mitre.org/data/definitions/20.html
К началу