☁️Entra IDApplications

Détournement d'URI de redirection Entra ID : URLs wildcard et flux implicite

Des URLs de réponse en wildcard, des URI de redirection en HTTP et le flux implicite se combinent pour permettre aux attaquants de voler des jetons Entra ID en direct depuis des inscriptions d'application.

Younes AZABARPar Younes AZABAR10 min de lecture
Détournement d'URI de redirection Entra ID : URLs wildcard et flux implicite

Qu'est-ce que le détournement d'URI de redirection Entra ID

Une URI de redirection Entra ID — les docs Microsoft l'appellent aussi une URL de réponse (reply URL) — est le point de destination vers lequel la plateforme d'identité Microsoft redirige un utilisateur, avec un jeton ou un code d'autorisation, une fois qu'il s'est authentifié et a donné son consentement. Toute inscription d'application qui utilise le flux du code d'autorisation OAuth 2.0, le flux implicite (implicit grant flow), ou OpenID Connect doit déclarer à l'avance ses URI de redirection exactes ; Entra ID refuse de rediriger ailleurs et renvoie AADSTS50011 si la valeur de la requête de connexion ne correspond à aucune de celles enregistrées.

Cette étape de correspondance constitue à elle seule toute la frontière de sécurité. Trois choix de configuration sur une seule inscription d'application suffisent à l'affaiblir au point de laisser un attaquant repartir avec un jeton valide au lieu de l'application légitime :

  • URL de réponse avec wildcard (APP_REPLY_URL_WILDCARD) — un motif comme https://*.contoso.com au lieu d'une URL exacte.
  • URL de réponse en HTTP (APP_REPLY_URL_HTTP) — une URI de redirection qui n'est pas restreinte à https.
  • Flux implicite activé (APP_IMPLICIT_GRANT_ENABLED) — l'inscription d'application laisse toujours Entra ID renvoyer directement un jeton d'accès ou un jeton d'ID dans le navigateur, au lieu de passer par un échange de jeton côté serveur.

Chacun de ces points est de sévérité Élevée à lui seul dans le catalogue EtcSec. Combinés sur la même application, ils transforment un simple lien de phishing en un chemin d'exfiltration de jeton opérationnel — et ils s'ajoutent à d'autres risques d'inscription d'application qu'EtcSec surveille, comme les inscriptions d'application sur-privilégiées, les identifiants obsolètes, et les permissions Graph API dangereuses.

Comment ça fonctionne

La correspondance exacte est tout l'intérêt, le wildcard la neutralise

Entra ID exige que les URI de redirection commencent par https, avec une exception étroite pour localhost en développement local — http://localhost/myapp est valide, http://contoso.com/callback ne l'est pas. Les wildcards sont un assouplissement distinct et optionnel de la règle de correspondance, pas de la règle de schéma : une inscription d'application limitée aux comptes professionnels ou scolaires peut, via l'éditeur de manifeste d'application, enregistrer https://*.contoso.com et faire en sorte qu'Entra ID traite tout sous-domaine correspondant comme autorisé. Le guide officiel de Microsoft sur les bonnes pratiques et limitations des URI de redirection est explicite : cette pratique doit être évitée ; selon la RFC 6749 section 3.1.2, un point de terminaison de redirection doit être une URI absolue, et lorsqu'une entrée wildcard correspond, Entra retire la chaîne de requête et le fragment de la redirection — c'est justement là qu'un jeton du flux implicite se trouverait.

La RFC 9700, les bonnes pratiques de sécurité actuelles de l'IETF pour OAuth 2.0, va plus loin qu'« éviter » : elle exige que les serveurs d'autorisation utilisent une correspondance exacte de chaîne pour les URI de redirection, avec pour seule exception le numéro de port sur les URI localhost des applications natives. La justification est concrète — des implémentations naïves de wildcard ont permis à des attaquants d'enregistrer quelque chose comme attaquant.exemple/.monsite.exemple et de passer une correspondance de sous-chaîne, et même une gestion correcte du wildcard laisse subsister la prise de contrôle de sous-domaine comme chemin d'attaque réel : tout sous-domaine qu'un attaquant peut mettre en place (un CNAME abandonné, un hôte de développement oublié) devient une cible de redirection valide dès qu'il correspond au motif.

Le flux implicite remet le jeton à quiconque détient l'URL

Le flux du code d'autorisation garde l'échange de jeton sur un canal séparé : le navigateur ne voit jamais qu'un code de courte durée, que l'application échange ensuite contre un jeton de serveur à serveur. Le flux implicite saute cette étape — Entra ID renvoie directement le jeton d'accès ou le jeton d'ID dans la réponse /authorize, ajouté au fragment de l'URI de redirection. Ce comportement est contrôlé par inscription d'application via deux propriétés Microsoft Graph sur la ressource web de l'application : implicitGrantSettings.enableIdTokenIssuance et implicitGrantSettings.enableAccessTokenIssuance. Si l'une des deux vaut true, l'application peut demander un type de réponse token ou id_token et récupérer un jeton sans aucun échange côté serveur.

La RFC 9700 section 2.1.2 est directe sur la conséquence : les clients « NE DEVRAIENT PAS utiliser le flux implicite … à moins que l'injection de jeton d'accès dans la réponse d'autorisation ne soit empêchée et que les vecteurs de fuite de jeton mentionnés ne soient atténués ». Les vecteurs de fuite listés sont peu spectaculaires mais bien réels — un jeton placé dans un fragment d'URL peut se retrouver dans l'historique du navigateur, être réattaché par le user agent au fil des redirections, ou fuiter via un en-tête Referer vers un site tiers que la page porteuse du jeton se trouve lier. En plus de cela, un jeton du flux implicite n'a aucune contrainte d'expéditeur (sender-constraining) : rien ne le lie au client pour lequel il a été émis, donc une copie vaut l'original. La documentation Microsoft sur le flux implicit grant est arrivée à la même conclusion par un angle différent — l'abandon des cookies tiers par les navigateurs a cassé l'étape de renouvellement silencieux du flux — et déconseille désormais explicitement son usage aux développeurs, en renvoyant vers la RFC 9700 section 2.1.2 et en recommandant la migration vers le flux du code d'autorisation.

La chaîne d'attaque

Étape 1 — Trouver ou détourner une cible de redirection qui correspond

Si l'inscription d'application ciblée porte APP_REPLY_URL_WILDCARD — disons https://*.contoso.com/auth — l'attaquant n'a pas besoin de compromettre le domaine principal. N'importe quel sous-domaine qui résout, y compris celui d'un environnement de développement abandonné ou d'un enregistrement DNS orphelin laissé par un service mis hors service, correspond au motif et devient une cible de redirection d'apparence légitime pour Entra ID.

Étape 2 — Demander un jeton plutôt qu'un code

Avec APP_IMPLICIT_GRANT_ENABLED activé sur l'application, l'attaquant construit une URL de connexion visant le véritable client_id avec response_type=token (ou id_token token) et une redirect_uri réglée sur son point de terminaison correspondant, puis la diffuse comme lien de phishing. La victime s'authentifie sur la véritable page de connexion Entra ID — il n'y a aucun faux formulaire de connexion à repérer — et Entra ID redirige le navigateur vers le point de terminaison de l'attaquant avec le jeton attaché.

Étape 3 — Capturer le jeton en clair

Lorsque APP_REPLY_URL_HTTP est également présent, ou lorsque le point de terminaison contrôlé par l'attaquant se contente de journaliser ce qu'il reçoit, le jeton qui voyage dans l'URL peut être capturé directement, journalisé par un proxy, ou exposé via les vecteurs de fuite documentés par la RFC 9700 — historique du navigateur, en-têtes Referer sur les liens sortants de la page d'atterrissage, ou réattachement lors d'une redirection ultérieure.

Étape 4 — Rejouer le jeton sans aucun secret client requis

Comme le flux implicite émet un jeton porteur (bearer token) sans contrainte d'expéditeur, l'attaquant l'utilise directement contre Microsoft Graph ou toute ressource pour laquelle il a été scopé, en se faisant passer pour la victime, aussi longtemps qu'il reste valide. Ce flux ne comporte pas de refresh token, la fenêtre est donc bornée par la durée de vie du jeton d'accès — mais rien d'autre ne sépare la capture de la réutilisation. C'est un mécanisme différent du phishing par consentement OAuth, qui piège un utilisateur pour qu'il autorise une application malveillante plutôt que d'intercepter un jeton destiné à une application légitime — mais les deux se terminent avec un attaquant en possession d'un identifiant valide vers votre tenant.

Détection

La configuration des URI de redirection et les paramètres du flux implicite vivent sur l'objet application, pas dans les journaux d'activité de connexion — il s'agit donc d'un contrôle d'inventaire via Microsoft Graph plutôt que d'une requête SIEM :

IndicateurOù vérifierCe que cela signifie
Une entrée web.redirectUris contenant *GET /applications/{id}web.redirectUrisURL de réponse avec wildcard — APP_REPLY_URL_WILDCARD
Une entrée web.redirectUris commençant par http:// et différente de localhostLe même tableau web.redirectUrisURL de réponse en clair — APP_REPLY_URL_HTTP
web.implicitGrantSettings.enableIdTokenIssuance ou enableAccessTokenIssuance réglé sur trueGET /applications/{id}web.implicitGrantSettingsFlux implicite ou hybride toujours autorisé — APP_IMPLICIT_GRANT_ENABLED

Dans le centre d'administration Microsoft Entra, la même information est visible par application sous Inscriptions d'applications → [application] → Authentification : la liste des URI de redirection de la plateforme Web, et les cases Octroi implicite et flux hybrides pour les jetons d'ID et les jetons d'accès.

Correction (Remediation)

  1. Remplacer les URI de redirection en wildcard par des URI exactes et absolues. Lister individuellement chaque point de terminaison de rappel réel plutôt qu'un motif. Si le nombre de sous-domaines rend cela ingérable, Microsoft documente une alternative par paramètre state : une seule URI de redirection partagée, protégée contre le CSRF, plus une valeur state spécifique à l'application, au lieu d'une correspondance wildcard.
  2. Retirer toute URI de redirection http:// non-localhost. Entra ID rejette déjà les nouvelles entrées sans https en dehors de localhost, mais les inscriptions d'application héritées peuvent en conserver une datant d'avant l'application de cette restriction ; vérifier directement web.redirectUris plutôt que de supposer que le centre d'administration l'aurait bloquée à la création.
  3. Désactiver le flux implicite. Régler implicitGrantSettings.enableIdTokenIssuance et enableAccessTokenIssuance sur false (ou décocher les deux cases dans le portail), sauf si une intégration héritée en dépend explicitement.
  4. Migrer vers le flux du code d'autorisation avec PKCE. La RFC 9700 section 2.1.1 exige PKCE pour les clients publics et le recommande pour les clients confidentiels ; les bibliothèques MSAL de Microsoft implémentent l'échange de code et le challenge PKCE à votre place, il s'agit donc généralement d'un remplacement de bibliothèque plutôt que d'un projet de réimplémentation de protocole.
  5. Revérifier la plateforme après migration. Une application monopage qui a toujours besoin d'un flux limité au navigateur doit migrer vers le flux du code d'autorisation avec PKCE sur la plateforme SPA, et non rester sur Web avec le flux implicite activé.

Comment EtcSec détecte cela

L'audit Azure d'EtcSec lit web.redirectUris et web.implicitGrantSettings de chaque inscription d'application via Microsoft Graph, et lève APP_REPLY_URL_WILDCARD pour toute entrée wildcard, APP_REPLY_URL_HTTP pour toute entrée http:// non-localhost, et APP_IMPLICIT_GRANT_ENABLED lorsque l'un ou l'autre indicateur d'émission du flux implicite vaut true — les trois limités à la plateforme Web, comme indiqué plus haut. Ce cluster n'est qu'une partie d'une revue plus large ; voir notre guide pratique pour auditer la sécurité de Microsoft Entra ID pour la checklist complète au-delà des inscriptions d'application.

Explorez les pages de sécurité des identités liées à ce sujet