Мосты WebView – Native

Категория 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() разрешайте сообщения только из доверенных доменов. Для этого не используйте символ * в качестве целевого источника, а явно указывайте домен отправителя.


Ресурсы