Open redirect (CWE-601) : 6 variantes du paramètre URL (CVSS 6.1) au vol de code OAuth (CVSS 9.8) — référence rapide et workflow de détection.
TL;DR
endsWith sont toujours contournablesLes vulnérabilités de redirection ouverte partagent une cause racine — une entrée utilisateur contrôlée aboutit dans un mécanisme de redirection sans validation d'hôte — mais diffèrent suffisamment par localisation et déclencheur pour nécessiter une approche de test et de remédiation distincte pour chaque variante.
Le score CVSS de base pour une redirection ouverte isolée est 6.1. Il monte fortement quand la redirection est positionnée dans un flux sensible.
La forme classique. Un paramètre nommé next, return, redirect, goto, url, dest est passé à la fonction de redirection du serveur sans validation. Le serveur émet un 30x avec un header Location contenant l'URL de l'attaquant.
Gravité : CVSS 6.1 en isolation ; 8.6+ si le paramètre est sur un endpoint gérant des tokens ou un état sensible.
Détail complet : Redirection par Paramètre URL
L'application construit des URLs de redirection en utilisant le header de requête Host ou X-Forwarded-Host plutôt qu'une URL de base codée en dur. Un attaquant injecte un hôte personnalisé, causant l'URL de redirection à pointer vers son domaine. Particulièrement présent dans les flux de réinitialisation de mot de passe — le lien de réinitialisation dans l'email contient l'hôte injecté.
Gravité : CVSS 6.1-8.1 selon si la chaîne de redirection permet une prise de contrôle de compte.
Détail complet : Redirection par Header
Le code côté client lit une URL depuis window.location.search, document.referrer, window.location.hash, ou localStorage, puis l'assigne à window.location ou document.location.href sans validation. Pas de réponse 30x côté serveur — la redirection se produit entièrement dans le navigateur. Les scanners automatisés manquent cela sauf s'ils exécutent JavaScript.
Gravité : CVSS 4.3-7.4. Plus bas car l'attaquant nécessite une livraison par ingénierie sociale, mais plus difficile à détecter automatiquement.
Détail complet : Redirection JavaScript DOM
Le serveur d'autorisation OAuth n'applique pas la correspondance exacte redirect_uri selon la RFC 6749 §3.1.2. Un attaquant injecte une redirection ouverte sur un domaine enregistré dans le paramètre redirect_uri — le serveur d'autorisation traite le domaine enregistré comme valide et ajoute le code d'autorisation avant de rediriger. Le code arrive à l'endpoint de l'attaquant via la chaîne de redirection ouverte.
Gravité : CVSS 8.6-9.8 — le vol de code d'autorisation permet une prise de contrôle de compte complète.
Détail complet : Détournement OAuth redirect_uri
Le serveur de l'application récupère une URL fournie par l'utilisateur (chargeur de document, webhook, proxy d'image, générateur PDF). Une allowlist SSRF autorise un domaine de confiance ayant une redirection ouverte. Le serveur suit la redirection vers un endpoint interne ou cloud. Cela transforme une redirection ouverte d'une primitive de phishing côté client en une primitive SSRF côté serveur.
Gravité : CVSS 8.6-9.1 quand des identifiants de métadonnées cloud sont accessibles (CVE-2024-2376, LangChain).
Détail complet : Chaîne Redirection Ouverte vers SSRF
L'application expose un endpoint de redirection acceptant l'URL de destination comme segment de chemin : /go/https://evil.com, /redirect/https://evil.com, /r/<url>. Souvent trouvé dans les raccourcisseurs d'URL legacy, le suivi de liens ou les systèmes d'affiliation.
Gravité : CVSS 6.1. Impact identique à la redirection par paramètre URL ; structure d'URL d'exploitation différente. Couvert dans Redirection par Paramètre URL.
La plupart des corrections de redirection ouverte tentent une validation par chaîne d'URL. Elles échouent car des parseurs différents interprètent la même chaîne différemment. La norme WHATWG URL (Chrome, Firefox, Edge, Safari), RFC 3986, et le url.parse legacy de Node.js arrivent à des conclusions différentes pour la même chaîne d'entrée — ce qui constitue le mécanisme derrière la plupart des payloads de bypass :
| Entrée | WHATWG URL | RFC 3986 | Node.js legacy url.parse |
|---|---|---|---|
//evil.com | host=evil.com (relatif au protocole) | invalide (pas de schéma) | host=evil.com |
\evil.com | host=evil.com (normalise \ en /) | invalide | host=evil.com (legacy traite \ comme /) |
https:evil.com | host=evil.com | host=evil.com | scheme=https path=evil.com |
https://evil.com\@trusted.com | host=evil.com (\@ est séparateur de chemin) | host=evil.com | host=trusted.com (legacy parse \@ comme userinfo) |
//evil%2Ecom | host=evil.com (décode le pourcent) | host=evil%2Ecom (brut) | host=evil%2Ecom |
La surface d'attaque : un backend utilisant Python urlparse rejette \evil.com (voit un netloc vide) tandis que le moteur WHATWG du navigateur le résout en https://evil.com. Un filtre basé sur le parsing conforme RFC 3986 peut rejeter //evil.com comme manquant de schéma, tandis que Chrome le suit comme URL relative au protocole. Le url.parse legacy de Node.js traite \ comme séparateur de chemin, produisant host=evil.com pour \evil.com — tandis que le nouveau new URL() WHATWG le résout également en evil.com. Il n'existe pas de cohérence de parseur URL entre les runtimes.
La seule correction fiable : parser l'URL avec le même parseur que le navigateur (WHATWG new URL() en Node.js, ou une bibliothèque dédiée), extraire le hostname, et le comparer contre un Set exact de hostnames autorisés. Ne jamais opérer sur la chaîne d'URL brute.
Le paramètre de redirection est-il sur un endpoint OAuth/SAML/SSO ?
Oui → redirect-oauth → CVSS 8.6-9.8 (vol de code d'autorisation possible)
Non → Le serveur récupère-t-il l'URL lui-même ?
Oui → redirect-ssrf-chain → CVSS 8.6+ (primitive SSRF)
Non → L'URL de redirection est-elle dans un email (ex: réinitialisation) ?
Oui → redirect-header ou redirect-url-param → CVSS 6.1-8.1
Non → Uniquement côté client (window.location) ?
Oui → redirect-javascript → CVSS 4.3-7.4
Non → Standard redirect-url-param → CVSS 6.1Comprendre les transitions de score CVSS est essentiel pour trier quelles redirections reporter et comment communiquer leur impact.
CVSS 6.1 — Redirection par Paramètre URL Isolée
Le vecteur de base est CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:L/A:N. L'interaction utilisateur est requise (UI:R) car la victime doit cliquer sur un lien forgé. La Confidentialité et l'Intégrité sont toutes deux Faibles car la redirection en isolation envoie seulement la victime vers un domaine attaquant — sans divulgation automatique de données. Le Périmètre est Modifié (S:C) car la redirection traverse la frontière de confiance du domaine d'origine.
CVSS 8.1 → 8.6 — Empoisonnement Header Host / Reset de Mot de Passe
Quand la redirection est construite depuis le header Host ou X-Forwarded-Host et intégrée dans un email de reset de mot de passe, l'impact Intégrité monte à Élevé (I:H) : un attaquant peut intercepter le token de reset et prendre le contrôle du compte victime. L'impact Confidentialité monte aussi car le token (un identifiant) est divulgué. Cela élève le vecteur à environ CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N = 8.1 ou plus selon si PR:N s'applique (ce qui est le cas si aucune authentification n'est requise pour déclencher le flux de reset).
CVSS 8.6 — OAuth redirect_uri + Vol de Code d'Autorisation
Dans la chaîne OAuth, le Code d'Autorisation arrive directement à l'endpoint de l'attaquant. L'impact Confidentialité est Élevé (C:H) — le code d'autorisation est équivalent à un identifiant de session. L'Intégrité est Élevée (I:H) — l'attaquant peut utiliser le code pour agir en tant que victime. Le Périmètre est Modifié. Le vecteur CVSS de base : AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N = 8.6. Le score atteint 9.8 quand aucune interaction utilisateur n'est requise ou quand l'attaquant peut ignorer le client_secret (clients publics, validation serveur cassée).
CVSS 8.6 → 9.1 — Redirection Ouverte → SSRF → Métadonnées Cloud Quand le serveur suit la redirection côté serveur, UI:R tombe à UI:N (pas de clic victime requis — le serveur récupère autonomement). Cela seul fait monter le score. La Confidentialité est Élevée quand des identifiants IAM sont accessibles. Le score atteint 9.1 quand l'accès aux identifiants cloud permet un mouvement latéral vers un magasin de données à haute valeur. CVE-2024-2376 (LangChain) a été noté 8.6 car l'impact direct était la divulgation d'identifiants.
Chaque variante de redirection ouverte produit un ensemble distinct de signaux observables lors des tests :
| Variante | Signal Serveur | Signal Navigateur | Outil Automatisé |
|---|---|---|---|
| Paramètre URL | 30x Location: <canary> dans la réponse HTTP | Navigateur va vers le domaine canary | OpenRedireX, templates nuclei redirect |
| Header | Email de reset contient l'hôte injecté, OU corps de réponse reflète X-FH | Aucun (livraison email requise ou OOB) | Param Miner (Burp), réflexion header httpx |
| JavaScript DOM | Pas de 30x côté serveur du tout | window.location du navigateur change vers canary (sans requête réseau serveur) | Dalfox --open-redirect, Chrome headless |
| OAuth redirect_uri | Serveur d'autorisation retourne 302 avec code ajouté à l'URI forgé | Code arrive au serveur canary | Burp OAuth Scanner, Repeater manuel |
| Chaîne SSRF | Callback DNS/HTTP OOB depuis l'IP serveur (pas le navigateur victime) | Aucun | Interactsh + nuclei SSRF, Burp Collaborator |
| Chemin | 30x Location: <canary> pour pattern /go/<canary> | Navigateur navigue | Templates redirect nuclei basés chemin |
La source la plus courante de faux positifs : les redirections same-origin où le header Location pointe vers un chemin ou le même domaine. Toujours extraire l'eTLD+1 de la valeur Location et vérifier qu'il diffère de l'eTLD+1 de la cible avant de reporter.
| Méthode | Outil | Signal |
|---|---|---|
| Fuzzing de paramètres | OpenRedireX, nuclei | Location 30x contient le domaine canary |
| DOM-based | Burp Scanner, dalfox --open-redirect | Assignation window.location avec param |
| Header Host | Param Miner (Burp) | Email/réponse contient le Host injecté |
| Flux OAuth | Manuel + Burp Repeater | Code d'autorisation dans redirection vers attaquant |
| SSRF via redirect | Templates nuclei SSRF + Interactsh | Callback DNS/HTTP OOB depuis le serveur |
| Variante | Correction Principale |
|---|---|
| Paramètre URL | Allowlist hostname Set — correspondance exacte, pas endsWith |
| Header | Coder en dur l'URL de base dans variable d'env, jamais depuis header Host |
| JavaScript DOM | Valider avec constructeur WHATWG URL avant assignation window.location |
| OAuth redirect_uri | Comparaison exacte de chaîne RFC 6749 §3.1.2 ; pas de wildcards |
| Chaîne SSRF | Valider la destination finale après suivi des redirections, pas juste l'URL initiale |
| Chemin | Remplacer par clé de redirection opaque mappée côté serveur |
Les redirections ouvertes se manifestent sous six formes : (1) redirection par paramètre URL — ?next=, ?return=, ?goto= passés à res.redirect() sans validation ; (2) redirection par header — Host ou X-Forwarded-Host injectés dans la construction Location ; (3) redirection JavaScript DOM — window.location = paramètre dans le navigateur ; (4) détournement OAuth redirect_uri — vol de code d'autorisation via URL de callback non validée ; (5) chaîne SSRF — suivi de redirection côté serveur atteignant des endpoints internes ; (6) redirection par chemin — /go/https://evil.com.
Prioriser par potentiel de gravité : (1) OAuth redirect_uri d'abord — le vol de code d'autorisation est critique ; (2) tout paramètre nommé next/return/goto sur les endpoints de login ou logout ; (3) header Host sur la réinitialisation de mot de passe — prise de contrôle de compte ; (4) tout suivi de redirection côté serveur (potentiel de chaîne SSRF) ; (5) redirections JavaScript côté client — DOM-based, plus difficiles à détecter automatiquement.
Le CVSS de base est 6.1 (Moyen). Escalader vers Élevé si : la redirection est sur un endpoint OAuth/SAML (vol de token possible), le serveur suit les redirections côté serveur (chaîne SSRF), ou l'endpoint gère des opérations sensibles comme la réinitialisation de mot de passe. Escalader vers Critique si : des codes d'autorisation sont exposés, des identifiants cloud accessibles via chaîne SSRF, ou une prise de contrôle de compte complète est démontrable.
OpenRedireX pour le fuzzing de paramètres ; templates nuclei pour les vérifications spécifiques aux CVE ; Burp Suite Scanner pour la détection passive + active ; Param Miner pour les variantes de header Host ; Dalfox v3+ pour la détection DOM-based. Aucun outil seul ne couvre toutes les variantes — combinez le fuzzing de paramètres avec les tests OAuth manuels et l'injection de headers.
CWE-601 est la classe spécifique pour la redirection d'URL vers des sites non fiables. CWE-20 (Improper Input Validation) est la classe parente. L'injection de header Host causant une redirection est souvent classifiée CWE-20 ou CWE-444 selon le mécanisme. Quand le résultat est spécifiquement une redirection vers une URL contrôlée par l'attaquant, CWE-601 est la classification principale correcte.
Le SSRF direct contrôle directement l'URL que le serveur récupère. Le SSRF via redirection ouverte est indirect : l'attaquant fournit une URL vers un domaine de confiance qui a une redirection ouverte, et le serveur suit la redirection vers un endpoint interne. Les filtres SSRF autorisent le domaine de confiance mais ne bloquent pas la redirection. La différence clé : le SSRF via redirection contourne les allowlists SSRF basées sur l'hôte.
Oui. CSP ne prévient pas les redirections ouvertes. CSP restreint où les scripts, frames et ressources se chargent — il ne contrôle pas la gestion par le navigateur des réponses de redirection HTTP. Une redirection ouverte envoie le navigateur vers une nouvelle origine entièrement, hors du contexte CSP. Le domaine de l'attaquant n'est soumis à aucune contrainte CSP.
Le calculateur CVSS HackerOne note une redirection ouverte isolée en Faible à Moyen (CVSS 6.1). Quand chaînée avec le vol de token OAuth ou SSRF, les reports sont notés Élevé à Critique et rapportent 1 000 à 10 000+ $. HackerOne #112614 (redirection ouverte OAuth Twitter) a payé 1 470 $. Forgejo CVE-2025-30215 (OAuth redirect_uri) était noté CVSS 8.1.
Contournements courants : double encodage URL (%2540 pour @, %252F pour /) ; normalisation Unicode (point pleine largeur %EF%BC%8E, espace zéro-largeur %E2%80%8B) ; préfixe caractère de contrôle (%09 tabulation, %0A retour à la ligne avant https://) ; null byte (%00) entre domaine de confiance et domaine attaquant ; encodage d'entité HTML si l'entrée passe par HTML avant la redirection.