OWASP-Kategorie: MASVS-PLATFORM: Platform Interaction
Übersicht
Eine native Bridge, manchmal auch als JavaScript-Bridge bezeichnet, ist ein Mechanismus, der
die Kommunikation zwischen einer WebView und nativem Android-Code mithilfe der
Methode addJavascriptInterface ermöglicht. So kann eine bidirektionale Kommunikation zwischen JavaScript-Code, der in der WebView ausgeführt wird, und dem Java-Code der Android-Anwendung stattfinden. Die Methode addJavascriptInterface macht ein Java-Objekt für alle Frames einer WebView verfügbar. Jeder Frame kann auf den Objektnamen zugreifen und Methoden dafür aufrufen. Es gibt jedoch keinen Mechanismus, mit dem die Anwendung den Ursprung des aufrufenden Frames in der WebView überprüfen kann. Das birgt Sicherheitsrisiken, da die Vertrauenswürdigkeit des Inhalts unbestimmt bleibt.
Eine native Bridge kann auch mit HTML-Nachrichtenkanälen implementiert werden. Dazu wird
Androids WebViewCompat.postWebMessage oder
WebMessagePort.postMessage verwendet, um mit dem JavaScript
Window.postMessage zu kommunizieren. WebViewCompat.postWebMessage und WebMessagePort.postMessage können JavaScript-Nachrichten akzeptieren, die über Window.postMessage gesendet werden und in der WebView ausgeführt werden.
Mit nativen Bridges sind mehrere Risiken verbunden:
- Bridges auf Basis von JavascriptInterface:
- Die Methode
addJavascriptInterfacefügt ein bereitgestelltes Java-Objekt in jeden Frame der WebView ein, einschließlich iFrames. Das bedeutet, dass sie anfällig für Angriffe durch böswillige Dritte ist, die Frames in eine legitime Website einfügen. Anwendungen, die auf API-Level 16 oder niedriger ausgerichtet sind, sind besonders anfällig für Angriffe, da mit dieser Methode JavaScript die Hostanwendung steuern kann. - Wenn nicht vertrauenswürdige, von Nutzern bereitgestellte Inhalte in WebViews mit aktivierter nativer Bridge wiedergegeben werden, sind Cross-Site-Scripting-Angriffe (XSS) möglich.
- Die Methode
- Bridges auf Basis von MessageChannel:
- Wenn keine Ursprungsprüfungen für Endpunkte von Nachrichtenkanälen durchgeführt werden, werden Nachrichten von jedem Absender akzeptiert, auch solche, die schädlichen Code enthalten.
- Es ist möglich, Java versehentlich für beliebiges JavaScript verfügbar zu machen.
Auswirkungen
Böswillige Akteure können die Methoden addJavascriptInterface, postWebMessage und postMessage nutzen, um auf eine WebView zuzugreifen, sie zu manipulieren oder von ihnen kontrollierten Code einzuschleusen. Das kann dazu führen, dass Nutzer auf schädliche Websites weitergeleitet werden, schädliche Inhalte geladen werden oder schädlicher Code auf ihren Geräten ausgeführt wird, der vertrauliche Daten extrahieren oder Rechteausweitung erzielen kann.
Risiko: Risiken von addJavascriptInterface
WebView implementiert grundlegende Funktionen eines Browsers wie Seitenrendering, Navigation und JavaScript-Ausführung. WebView kann in einer Anwendung verwendet werden, um Webinhalte als Teil eines Aktivitätslayouts anzuzeigen. Wenn Sie eine native Bridge in einer WebView mit der Methode addJavascriptInterface implementieren, können Sicherheitsprobleme wie Cross-Site-Scripting (XSS) entstehen. Angreifer können auch nicht vertrauenswürdige Inhalte über die Schnittstelleneinschleusung laden und die Hostanwendung auf unbeabsichtigte Weise manipulieren, indem sie Java-Code mit den Berechtigungen der Hostanwendung ausführen.
Gegenmaßnahmen
JavaScript deaktivieren
In Szenarien, in denen WebView kein JavaScript benötigt, rufen Sie
setJavaScriptEnabled nicht in WebSettings auf (z. B. beim
Anzeigen statischer HTML-Inhalte). Standardmäßig ist die JavaScript-Ausführung in WebView deaktiviert.
JavaScript-Schnittstelle beim Laden nicht vertrauenswürdiger Inhalte entfernen
Achten Sie darauf, dass Objekte aus der JavaScript-Schnittstelle entfernt werden, indem Sie
removeJavascriptInterface aufrufen, bevor nicht vertrauenswürdige Inhalte von der
WebView geladen werden. Das kann beispielsweise in einem Aufruf von
shouldInterceptRequest erfolgen.
Kotlin
webView.removeJavascriptInterface("myObject")
Java
webView.removeJavascriptInterface("myObject");
Webinhalte nur über HTTPS laden
Wenn Sie nicht vertrauenswürdige Inhalte laden müssen, achten Sie darauf, dass die WebView Webinhalte über
eine verschlüsselte Verbindung lädt (siehe auch unsere Richtlinien zu Cleartext
Communications). Verhindern Sie, dass der anfängliche Seitenaufbau über unverschlüsselte Verbindungen durchgeführt wird, indem Sie android:usesCleartextTraffic auf false in der AndroidManifest Datei setzen oder HTTP-Traffic in einer Netzwerksicherheitskonfiguration deaktivieren. Weitere Informationen finden Sie in der usesCleartextTraffic Dokumentation zu mehr
Informationen.
XML
<application
android:usesCleartextTraffic="false">
<!-- Other application elements -->
</application>
Damit Weiterleitungen und weiteres Browsen in der App nicht über unverschlüsselten
Traffic erfolgen, prüfen Sie das HTTP-Schema in loadUrl oder
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);
}
}
}
Nicht vertrauenswürdige Inhalte validieren
Wenn externe Links in einer WebView geladen werden, validieren Sie sowohl das Schema als auch den Host (Domains auf die Zulassungsliste setzen). Alle Domains, die nicht auf der Zulassungsliste stehen, sollten stattdessen vom Standardbrowser geöffnet werden.
Nicht vertrauenswürdige Inhalte nicht laden
Laden Sie nach Möglichkeit nur streng skalierte URLs und Inhalte, die dem App-Entwickler gehören, in die WebView.
Keine vertraulichen Daten verfügbar machen
Wenn Ihre Anwendung mit einer WebView auf vertrauliche Daten zugreift, sollten Sie die
clearCache Methode verwenden, um alle lokal gespeicherten Dateien zu löschen, bevor Sie die
JavaScript-Schnittstelle verwenden. Sie können auch serverseitige Header wie „no-store“ verwenden, um anzugeben, dass eine Anwendung bestimmte Inhalte nicht im Cache speichern soll.
Keine vertraulichen Funktionen verfügbar machen
Wenn Ihre Anwendung vertrauliche Berechtigungen erfordert oder vertrauliche Daten erfasst, achten Sie darauf, dass sie aus Code in der Anwendung aufgerufen wird und dass Nutzer deutlich darüber informiert werden. Verwenden Sie keine JavaScript-Schnittstellen für vertrauliche Vorgänge oder Nutzerdaten.
Auf API-Level 21 oder höher ausrichten
Eine sichere Möglichkeit, die Methode addJavascriptInterface zu verwenden, besteht darin, auf API-Level 21 oder höher auszurichten und sicherzustellen, dass die Methode nur aufgerufen wird, wenn sie auf API-Level 21 oder höher ausgeführt wird. Vor API-Level 21 konnte JavaScript die Reflektion verwenden, um auf die öffentlichen Felder eines eingefügten Objekts zuzugreifen.
Risiko: Risiken von MessageChannel
Wenn die Ursprungsprüfung in postWebMessage() und postMessage() fehlt, können Angreifer Nachrichten abfangen oder Nachrichten an native Handler senden.
Gegenmaßnahmen
Wenn Sie postWebMessage() oder postMessage() einrichten, lassen Sie nur Nachrichten von vertrauenswürdigen Domains zu. Verwenden Sie dazu nicht * als Zielursprung, sondern geben Sie stattdessen explizit die erwartete Absenderdomain an.
Ressourcen
- Best Practices für postMessage()
- Dokumentation zu addJavascriptInterface
- Dokumentation zu postMessage()
- Dokumentation zu WebMessagePort.postMessage()
- Dokumentation zu WebViewClient.shouldInterceptRequest
- Dokumentation zu Sicherheitshinweisen zu addJavascriptInterface
- Dokumentation zu clearCache
- Dokumentation zu removeJavascript
- JavaScript in WebViews aktivieren