Категория OWASP: MASVS-PLATFORM: взаимодействие с платформой.
Обзор
Нативный мост, также известный как мост JavaScript, – это механизм, который упрощает обмен данными между WebView и нативным кодом Android. Он реализуется с помощью метода addJavascriptInterface. Это позволяет наладить двустороннюю связь между кодом JavaScript, выполняемым в WebView, и кодом Java приложения Android. Метод addJavascriptInterface предоставляет доступ к объекту Java всем фреймам WebView, и любой фрейм может получить доступ к имени объекта и вызвать его методы. Однако в приложении нет механизма для проверки источника вызывающего фрейма в WebView, что вызывает проблемы с безопасностью, поскольку надежность контента остается неопределенной.
Нативный мост также можно реализовать с помощью каналов сообщений HTML, используя WebViewCompat.postWebMessage или WebMessagePort.postMessage Android для связи с Window.postMessage JavaScript. WebViewCompat.postWebMessage и WebMessagePort.postMessage могут принимать сообщения JavaScript, отправленные через Window.postMessage, которые будут выполняться в WebView.
С нативными мостами связано несколько рисков:
- Мосты на основе JavascriptInterface:
- Метод
addJavascriptInterfaceвнедряет предоставленный объект Java в каждый фрейм WebView, включая iframe. Это значит, что он уязвим для атак, при которых злоумышленники внедряют фреймы в легитимный сайт. Приложения, предназначенные для целевого уровня API 16 или более ранних версий, особенно уязвимы для атак, поскольку этот метод позволяет JavaScript управлять хост-приложением. - Отображение ненадежного контента, предоставленного пользователем, в компонентах WebView с включенным нативным мостом позволяет проводить атаки с межсайтовым скриптингом (XSS).
- Метод
- Мосты на основе MessageChannel:
- Если не проверять происхождение конечных точек каналов сообщений, то сообщения будут приниматься от любых отправителей, в том числе содержащие вредоносный код.
- Java может быть случайно открыт для произвольного кода JavaScript.
Влияние
Методы addJavascriptInterface, postWebMessage и postMessage могут использоваться злоумышленниками для доступа к коду, его изменения или внедрения в WebView. В результате пользователи могут быть перенаправлены на вредоносные сайты, загрузить вредоносный контент или запустить на своих устройствах вредоносный код, который может извлечь конфиденциальные данные или повысить привилегии.
Риск: addJavascriptInterface
WebView реализует базовые функции браузера, такие как отрисовка страниц, навигация и выполнение JavaScript. WebView можно использовать в приложении для показа веб-контента в макете действия. Реализация нативного моста в WebView с помощью метода addJavascriptInterface может привести к проблемам с безопасностью, например межсайтовому скриптингу (XSS). Кроме того, злоумышленники могут загружать ненадежный контент через внедрение интерфейса и манипулировать размещаемым приложением, выполняя код Java с его разрешениями.
Предотвращение атак
Отключить JavaScript
Если в WebView не требуется JavaScript, не вызывайте setJavaScriptEnabled в WebSettings (например, при показе статического HTML-контента). По умолчанию выполнение JavaScript в WebView отключено.
Удалите интерфейс JavaScript при загрузке ненадежного контента
Убедитесь, что объекты из интерфейса JavaScript удаляются с помощью метода removeJavascriptInterface до загрузки ненадежного контента. Например, это можно сделать в вызове shouldInterceptRequest.
Kotlin
webView.removeJavascriptInterface("myObject")
Java
webView.removeJavascriptInterface("myObject");
Загружать веб-контент только по протоколу HTTPS
Если вам необходимо загружать ненадежный контент, убедитесь, что WebView загружает веб-контент через зашифрованное подключение (см. также наши рекомендации по передаче данных в виде открытого текста). Запретите загрузку начальной страницы по незашифрованным подключениям, задав для атрибута android:usesCleartextTraffic значение false в файле AndroidManifest или запретив трафик HTTP в конфигурации сетевой безопасности. Дополнительную информацию можно найти в документации по usesCleartextTraffic.
XML
<application
android:usesCleartextTraffic="false">
<!-- Other application elements -->
</application>
Чтобы переадресация и дальнейшая работа с приложением не происходили по незашифрованному трафику, проверьте схему HTTP в loadUrl или shouldInterceptRequest:
Kotlin
fun loadSecureUrl(webView: WebView?, url: String?) {
webView?.let { wv -> // Ensure valid WebView and URL
url?.let {
try {
val uri = URI(url)
if (uri.scheme.equals("https", ignoreCase = true)) { // Enforce HTTPS scheme for security
wv.loadUrl(url)
} else {
// Log an error or handle the case where the URL is not secure
System.err.println("Attempted to load a non-HTTPS URL: $url")
}
} catch (e: Exception) {
// Handle exception for improper URL format
System.err.println("Invalid URL syntax: $url")
}
}
}
}
Java
public void loadSecureUrl(WebView webView, String url) {
if (webView != null && url != null) { // Ensure valid WebView and URL
try {
URI uri = new URI(url);
String scheme = uri.getScheme();
if ("https".equalsIgnoreCase(scheme)) { // Enforce HTTPS scheme for security
webView.loadUrl(url);
} else {
// Log an error or handle the case where the URL is not secure
System.err.println("Attempted to load a non-HTTPS URL: " + url);
}
} catch (URISyntaxException e) {
// Handle exception for improper URL format
System.err.println("Invalid URL syntax: " + url);
}
}
}
Проверка ненадежного контента
Если в WebView загружаются внешние ссылки, проверяйте и схему, и хост (белый список доменов). Все домены, не входящие в белый список, должны открываться в браузере по умолчанию.
Не загружать ненадежный контент
По возможности загружайте в WebView только контент из строго ограниченного набора URL или контент, принадлежащий разработчику приложения.
Не раскрывайте конфиденциальные данные
Если ваше приложение получает доступ к конфиденциальным данным с помощью WebView, рекомендуем использовать метод clearCache, чтобы удалить все файлы, хранящиеся локально, прежде чем использовать интерфейс JavaScript. Вы также можете использовать заголовки на стороне сервера, например no-store, чтобы указать, что приложение не должно кешировать определенный контент.
Не раскрывайте конфиденциальные функции
Если вашему приложению нужны разрешения на доступ к конфиденциальной информации или оно собирает ее, убедитесь, что вызов функций, для работы которых требуется доступ к конфиденциальной информации, реализован через код внутри приложения и что вы раскрываете пользователям информацию об этом. Не используйте интерфейсы JavaScript для конфиденциальных операций или пользовательских данных.
Целевой уровень API 21 или выше
Один из безопасных способов использования метода addJavascriptInterface – установить целевой уровень API 21 или выше, чтобы метод вызывался только на устройствах с этим уровнем API. До API 21 JavaScript мог использовать рефлексию для доступа к общедоступным полям внедренного объекта.
Риск: MessageChannel
Отсутствие контроля источника в postWebMessage() и postMessage() может позволить злоумышленникам перехватывать сообщения или отправлять их нативным обработчикам.
Предотвращение атак
При настройке postWebMessage() или postMessage() разрешайте сообщения только из доверенных доменов. Для этого не используйте символ * в качестве целевого источника, а явно указывайте домен отправителя.
Ресурсы
- Рекомендации по использованию postMessage()
- Документация по addJavascriptInterface
- Документация по postMessage()
- Документация по WebMessagePort.postMessage()
- Документация по WebViewClient.shouldInterceptRequest
- Документация по безопасности, связанная с addJavascriptInterface
- Документация по clearCache
- Документация по removeJavascript
- включить JavaScript в WebView;