Catégorie OWASP : MASVS-PLATFORM : interaction avec la plate-forme
Présentation
Un pont natif, parfois appelé pont JavaScript, est un mécanisme qui
facilite la communication entre une WebView et le code Android natif, obtenu en
utilisant la addJavascriptInterface méthode. Cela permet une communication bidirectionnelle entre le code JavaScript exécuté dans la WebView et le code Java de l'application Android. La méthode addJavascriptInterface expose un objet Java à toutes les frames d'une WebView, et n'importe quelle frame peut accéder au nom de l'objet et appeler des méthodes sur celui-ci. Toutefois, l'application ne dispose d'aucun mécanisme pour vérifier l'origine de la frame appelante dans la WebView, ce qui soulève des problèmes de sécurité, car la fiabilité du contenu reste indéterminée.
Un pont natif peut également être implémenté avec des canaux de messages HTML à l'aide de
WebViewCompat.postWebMessage ou
WebMessagePort.postMessage d'Android pour communiquer avec le JavaScript
Window.postMessage. WebViewCompat.postWebMessage et WebMessagePort.postMessage peuvent accepter les messages JavaScript envoyés via Window.postMessage, qui seront exécutés dans la WebView.
Les ponts natifs présentent plusieurs risques :
- Ponts basés sur JavascriptInterface :
- La méthode
addJavascriptInterfaceinjecte un objet Java fourni dans chaque frame de la WebView, y compris les iFrames, ce qui signifie qu'elle est susceptible d'être attaquée par des tiers malveillants qui injectent des frames dans un site Web légitime. Les applications ciblant le niveau d'API 16 ou antérieur sont particulièrement exposées aux attaques, car cette méthode peut être utilisée pour autoriser JavaScript à contrôler l'application hôte. - La réflexion du contenu fourni par l'utilisateur non approuvé dans les WebView compatibles avec les ponts natifs permet les attaques de script intersites (XSS).
- La méthode
- Ponts basés sur MessageChannel :
- L'absence de vérification de l'origine sur les points de terminaison des canaux de messages signifie que les messages seront acceptés de n'importe quel expéditeur, y compris ceux contenant du code malveillant.
- Il est possible d'exposer accidentellement Java à un JavaScript arbitraire.
Impact
Les méthodes addJavascriptInterface, postWebMessage et postMessage peuvent être exploitées par des acteurs malveillants pour accéder, manipuler ou injecter du code qu'ils contrôlent dans une WebView. Cela peut entraîner la redirection des utilisateurs vers des sites malveillants, le chargement de contenu malveillant ou l'exécution de code malveillant sur leurs appareils, ce qui peut extraire des données sensibles ou permettre une élévation des privilèges.
Risque : risques liés à addJavascriptInterface
WebView implémente les fonctionnalités de base d'un navigateur, telles que le rendu des pages, la navigation et l'exécution de JavaScript. WebView peut être utilisé dans une application pour afficher du contenu Web dans une mise en page d'activité. L'implémentation d'un pont natif dans une WebView à l'aide de la méthode addJavascriptInterface peut créer des problèmes de sécurité tels que le script intersites (XSS) ou permettre aux pirates d'attaquer de charger du contenu non approuvé via l'injection d'interface et de manipuler l'application hôte de manière involontaire, en exécutant du code Java avec les autorisations de l'application hôte.
Stratégies d'atténuation
Désactiver JavaScript
Dans les scénarios où WebView ne nécessite pas JavaScript, n'appelez pas
setJavaScriptEnabled dans WebSettings (par exemple, lors de
l'affichage de contenu HTML statique). Par défaut, l'exécution de JavaScript est désactivée dans WebView.
Supprimer l'interface JavaScript lors du chargement de contenu non approuvé
Assurez-vous que les objets de l'interface JavaScript sont supprimés en appelant
removeJavascriptInterface avant que le contenu non approuvé ne soit chargé par la
WebView. Par exemple, cela peut être effectué lors d'un appel à
shouldInterceptRequest.
Kotlin
webView.removeJavascriptInterface("myObject")
Java
webView.removeJavascriptInterface("myObject");
Ne charger le contenu Web que via HTTPS
Si vous devez charger du contenu non approuvé, assurez-vous que la WebView charge le contenu Web via
une connexion chiffrée (consultez également nos consignes sur les communications
en texte clair). Empêchez le chargement initial de la page sur
des connexions non chiffrées en définissant android:usesCleartextTraffic sur false dans
le fichier AndroidManifest ou en interdisant le trafic HTTP dans une configuration de sécurité
réseau. Pour en savoir plus, consultez la usesCleartextTraffic documentation.
XML
<application
android:usesCleartextTraffic="false">
<!-- Other application elements -->
</application>
Pour vous assurer que les redirections et la navigation ultérieure dans l'application ne se produisent pas sur un trafic non chiffré, recherchez le schéma HTTP dans loadUrl ou
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);
}
}
}
Valider le contenu non approuvé
Si des liens externes sont chargés dans une WebView, validez à la fois le schéma et l'hôte (domaines de la liste d'autorisation). Tous les domaines qui ne figurent pas dans la liste d'autorisation doivent être ouverts par le navigateur par défaut.
Ne pas charger de contenu non approuvé
Si possible, ne chargez que les URL et le contenu restreints détenus par le développeur de l'application dans WebView.
Ne pas exposer de données sensibles
Si votre application accède à des données sensibles avec une WebView, envisagez d'utiliser la
clearCache méthode pour supprimer tous les fichiers stockés localement avant d'utiliser l'
interface JavaScript. Vous pouvez également utiliser des en-têtes côté serveur, tels que no-store, pour indiquer qu'une application ne doit pas mettre en cache un contenu particulier.
Ne pas exposer de fonctionnalités sensibles
Si votre application nécessite des autorisations sensibles ou collecte des données sensibles, assurez-vous qu'elle est appelée à partir du code de l'application et qu'une divulgation visible est fournie aux utilisateurs. Évitez d'utiliser des interfaces JavaScript pour les opérations sensibles ou les données utilisateur.
Cibler le niveau d'API 21 ou supérieur
Une façon sécurisée d'utiliser la méthode addJavascriptInterface consiste à cibler le niveau d'API 21 ou supérieur en vous assurant que la méthode n'est appelée que lorsqu'elle est exécutée sur le niveau d'API 21 ou supérieur. Avant l'API 21, JavaScript pouvait utiliser la réflexion pour accéder aux champs publics d'un objet injecté.
Risque : risques liés à MessageChannel
L'absence de contrôle de l'origine dans postWebMessage() et postMessage() pourrait permettre aux pirates d'intercepter des messages ou d'envoyer des messages à des gestionnaires natifs.
Stratégies d'atténuation
Lorsque vous configurez postWebMessage() ou postMessage(), n'autorisez que les messages provenant de domaines approuvés en évitant d'utiliser * comme origine cible et en spécifiant explicitement le domaine d'envoi attendu.
Ressources
- Bonnes pratiques concernant postMessage()
- Documentation sur addJavascriptInterface
- Documentation sur postMessage()
- Documentation sur WebMessagePort.postMessage()
- Documentation sur WebViewClient.shouldInterceptRequest
- Documentation sur les conseils de sécurité concernant addJavascriptInterface
- Documentation sur clearCache
- Documentation sur removeJavascript
- Activer JavaScript dans les WebView