WebViews – Chargement d'URI non sécurisé

Catégorie OWASP : MASVS-CODE : qualité du code

Présentation

Le chargement d'URI non sécurisé se produit lorsqu'une application Android ne parvient pas à évaluer correctement la validité d'un URI avant de le charger dans un WebView.

La raison sous-jacente de ce type de faille est qu'un URI se compose de plusieurs parties, parmi lesquelles au moins le schéma et l'hôte (de la partie autorité) doivent être vérifiés (par exemple, figurer sur la liste d'autorisation) avant que l'URI ne soit chargé dans un WebView ou utilisé en interne par l'application.

Voici les erreurs les plus courantes :

  • Vérifier l'hôte, mais pas le schéma, ce qui permet à un pirate informatique d'utiliser des schémas tels que http://, content:// ou javascript:// avec un hôte authentifié.
  • Ne pas correctement analyser l'URI, en particulier dans les cas où l'URI est reçu en tant que chaîne.
  • Valider le schéma, mais pas l'hôte (validation de l'hôte insuffisante).

Le dernier cas se produit généralement lorsque l'application doit autoriser les sous-domaines arbitraires d'un domaine principal. Ainsi, même si le nom d'hôte a été correctement extrait, l'appli utilise des méthodes telles que startsWith, endsWith, ou contains de la classe java.lang.String pour valider la présence d'un domaine principal dans la section des chaînes extraites. Lorsqu'elles sont mal utilisées, ces méthodes peuvent donner lieu à des résultats incorrects et forcer l'application à faire confiance à un hôte potentiellement malveillant.

Impact

L'impact peut varier en fonction du contexte dans lequel l'hôte est utilisé. Dans les cas où le chargement d'un URI malveillant (qui contourne le filtrage/la liste d'autorisation) dans un WebView peut entraîner un piratage de compte (par exemple, via l'hameçonnage), l'exécution de code (par exemple, le chargement de code JavaScript malveillant) ou un piratage de l'appareil (exploitation du code via un lien hypertexte).

Stratégies d'atténuation

Lors de la gestion des URI de chaîne, il est important d'analyser la chaîne en tant qu'URI, et de valider à la fois le schéma et l'hôte :

Kotlin

fun isUriTrusted(incomingUri: String, trustedHostName: String): Boolean {
    try {
        val uri = Uri.parse(incomingUri)
        return uri.scheme == "https" && uri.host == trustedHostName
    } catch (e: NullPointerException) {
        throw NullPointerException("incomingUri is null or not well-formed")
    }
}

Java

public static boolean isUriTrusted(String incomingUri, String trustedHostName)
    throws NullPointerException {
        try {
            Uri uri = Uri.parse(incomingUri);
            return uri.getScheme().equals("https") &&
            uri.getHost().equals(trustedHostName);
        } catch (NullPointerException e) {
            throw new NullPointerException(
                "incomingUri is null or not well-formed");
        }
    }

Pour la validation de l'hôte, après avoir isolé la partie URI correspondante, il est important de la valider entièrement (plutôt que partiellement) pour déterminer avec précision si l'hôte est approuvé ou non. Lorsque vous ne pouvez pas éviter d'utiliser les méthodes telles que startsWith ou endsWith, il est important d'utiliser la bonne syntaxe et de ne pas omettre les caractères ou symboles nécessaires (par exemple, endsWith nécessite le "." avant le nom de domaine pour une correspondance exacte). Négliger ces caractères peut donner lieu à des correspondances inexactes et compromettre la sécurité. Étant donné que les sous-domaines peuvent être imbriqués à l'infini, la mise en correspondance des expressions régulières n'est pas recommandée pour valider les noms d'hôte.

Contributeurs : Dimitrios Valsamaras et Michael Peck de Microsoft Threat Intelligence

Ressources