Возможность открытия произвольных данных в контексте WebView
![]() |
Критичность: ВЫСОКИЙ |
| Способ обнаружения: IAST |
Описание
WebView — это компонент, позволяющий отображать веб-страницы прямо внутри приложения. Приложение может использовать WebView для отображения HTML-контента или для интеграции веб-сервисов. Если данные, отображаемые в WebView, поступают от пользователя или стороннего приложения без должной проверки, это может привести к серьезным проблемам с безопасностью.
Пример использования WebView для загрузки данных из внешнего источника:
WebView myWebView = findViewById(R.id.webview);
String url = getIntent().getStringExtra("url");
myWebView.loadUrl(url);
В данном примере WebView загружает URL, который был передан из другого компонента. Это создает риск открытия произвольных данных, которые могут содержать вредоносный JavaScript или попытки получить доступ к локальным файлам.
Проблема
Если сторонние данные передаются в WebView без должной проверки, это может привести к следующим уязвимостям:
- Внедрение JavaScript (XSS) — Злоумышленник может передать вредоносный JavaScript-код, который будет выполнен в контексте WebView. Это может позволить злоумышленнику похитить данные, находящиеся в WebView, или получить доступ к чувствительной информации.
- Файловый доступ — Если WebView настроен на разрешение доступа к локальным файлам, злоумышленник может попытаться получить доступ к файловой системе устройства.
- Фишинг и обман пользователей — Злоумышленник может передать фишинговый URL, чтобы заставить пользователя ввести конфиденциальную информацию, такую как логин и пароль, на поддельной странице.
- Выполнение кода внутри приложения через JavaScript-интерфейс — Если в WebView используется JavaScript-интерфейс с методом
addJavascriptInterface(), злоумышленник может вызвать код приложения, что может привести к выполнению произвольных команд. Это особенно опасно, если данные для WebView поступают из ненадежных источников.
Рекомендации
-
Не используйте внешние данные без проверки для загрузки в WebView: Перед загрузкой данных в WebView убедитесь, что они проходят проверку и соответствуют требованиям безопасности. Используйте белый список (allow-list) разрешённых хостов и точную сверку, а не проверку по префиксу строки.
Проверка вида
url.startsWith("https://trusted-domain.com")небезопасна и легко обходится:https://trusted-domain.com.evil.com—evil.comявляется основным доменом, но строка начинается с ожидаемого префикса;https://trusted-domain.com@evil.com— всё, что до символа@, является user-info, фактический хост —evil.com;https://trusted-domain.com.evil.com/pathи подобные комбинации.
Корректный подход — разобрать URL через
Uri.parse(...), проверить, что схема строго равнаhttps, и что хост точно совпадает с одним из значений в белом списке (сравнение на равенство, а не на вхождение/префикс):import android.net.Uri; import java.util.Arrays; import java.util.HashSet; import java.util.Locale; import java.util.Set; private static final Set<String> ALLOWED_HOSTS = new HashSet<>(Arrays.asList( "trusted-domain.com", "www.trusted-domain.com" )); private boolean isUrlAllowed(String url) { if (url == null) { return false; } Uri uri = Uri.parse(url); String scheme = uri.getScheme(); String host = uri.getHost(); if (scheme == null || host == null) { return false; } // Схема строго https if (!"https".equals(scheme.toLowerCase(Locale.ROOT))) { return false; } // Точное совпадение хоста со значением из allow-list return ALLOWED_HOSTS.contains(host.toLowerCase(Locale.ROOT)); }String url = getIntent().getStringExtra("url"); if (isUrlAllowed(url)) { myWebView.loadUrl(url); } else { Log.e("WebView", "Неразрешенный URL"); }В этом примере URL разбирается на компоненты, после чего отдельно проверяются схема (
https) и хост (точное равенство значению из белого списка) перед загрузкой в WebView. -
Отключите JavaScript, если это возможно: Если нет необходимости в использовании JavaScript, его следует отключить, чтобы предотвратить возможное выполнение вредоносного кода. Это можно сделать с помощью настройки WebSettings:
-
Ограничьте доступ к локальным файлам: Убедитесь, что WebView не имеет доступа к локальным файлам, если это не требуется для работы приложения. Это можно сделать с помощью настройки:
-
Используйте WebViewClient для обработки ссылок: Используйте собственный WebViewClient для обработки переходов по ссылкам. Это позволит контролировать, какие URL будут загружены, и предотвратить загрузку вредоносных страниц.
Перегрузка
shouldOverrideUrlLoading(WebView, String)объявлена устаревшей (deprecated) начиная с API 24 (Android 7.0). Используйте перегрузку, принимающуюWebResourceRequest— из неё можно получить уже разобранныйUriзапроса черезrequest.getUrl()и применять ту же логику проверки (схемаhttps+ точная сверка хоста по белому списку):import android.webkit.WebResourceRequest; myWebView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { if (isUrlAllowed(request.getUrl().toString())) { return false; // Разрешить загрузку } else { Log.e("WebView", "Блокирован неразрешенный URL: " + request.getUrl()); return true; // Блокировать загрузку } } });Здесь повторно используется метод
isUrlAllowed(...)из примера выше, который проверяет схему и хост по белому списку. -
Очистите HTML-контент перед загрузкой: Если необходимо загрузить HTML-контент, который поступает от пользователя или другого приложения, используйте методы для очистки контента от возможных вредоносных вставок. Например, используйте библиотеки для фильтрации HTML, чтобы удалить вредоносный JavaScript.
-
Избегайте использования JavaScript-интерфейса без должной необходимости: Если требуется использовать метод
addJavascriptInterface(), убедитесь, что интерфейс безопасен и не предоставляет доступ к критическим методам или данным. Добавляйте интерфейсы только к проверенному контенту. -
Используйте безопасные настройки WebView: Отключите функции, которые могут повысить риск выполнения вредоносного кода или утечки данных:
Дополнительные примеры
Пример небезопасного использования WebView для загрузки произвольного URL:
В данном примере отсутствует проверка URL, что позволяет злоумышленнику передать вредоносный адрес для загрузки в WebView.
