Fixation de session par cookie (CWE-384) : l'attaquant plante un token connu via XSS ou injection de sous-domaine avant connexion, puis réutilise ce token pour accéder à la session authentifiée.
TL;DR
__Host- bloque la livraison inter-sous-domainesLa fixation de session par cookie est le mécanisme de livraison où un attaquant utilise le stockage de cookies du navigateur pour planter un identifiant de session pré-choisi avant que la victime ne se connecte. Contrairement à la fixation par paramètre URL — qui nécessite que la victime clique sur un lien spécifiquement construit — la fixation par cookie peut persister dans le navigateur à travers de multiples visites de pages. La victime ne voit aucune indication que son identifiant de session a été défini de l'extérieur.
L'attaque combine deux faiblesses : le mécanisme de livraison (comment l'attaquant définit le cookie) et la vulnérabilité fondamentale (le serveur ne régénère pas l'identifiant de session à l'authentification). Le durcissement des cookies avec HttpOnly, Secure, SameSite et le préfixe __Host- ferme la plupart des vecteurs de livraison. Mais sans régénération de session à la connexion, tout mécanisme de livraison qui contourne ces protections permet une fixation complète.
Les trois principaux vecteurs de livraison pour la fixation par cookie :
Livraison par XSS — un XSS stocké ou réfléchi exécute document.cookie = "session=VALEUR_ATTAQUANT; path=/". Ne fonctionne que si le cookie de session ne dispose pas de HttpOnly.
Livraison par interception réseau — un attaquant sur le chemin réseau intercepte une réponse HTTP et injecte un en-tête Set-Cookie. L'attribut Secure l'empêche sur HTTPS, mais les pages avec contenu mixte ou les attaques de rétrogradation HTTP suppriment cette protection.
Livraison par sous-domaine (cookie tossing) — un sous-domaine compromis émet Set-Cookie: session=CONNU; Domain=.example.com; Path=/. Le navigateur stocke le cookie et l'envoie au domaine parent sur toutes les requêtes futures.
-- Livraison par sous-domaine --
HTTP/1.1 200 OK
Host: abandonne.example.com
Set-Cookie: session=ID_CONNU_ATTAQUANT; Domain=.example.com; Path=/; Max-Age=86400
-- La victime visite ensuite l'application principale --
GET /login HTTP/1.1
Host: example.com
Cookie: session=ID_CONNU_ATTAQUANT
POST /login HTTP/1.1
Cookie: session=ID_CONNU_ATTAQUANT
email=victime@example.com&password=correct
HTTP/1.1 302 Found
Location: /tableau-de-bord
-- Pas de Set-Cookie : identifiant de session non renouvelé --| Vecteur de livraison | Prérequis | Défense cookie | Exemple |
|---|---|---|---|
| Injection de cookie via XSS | XSS stocké/réfléchi, session sans HttpOnly | HttpOnly | HackerOne #1629543 (GitLab) |
| Interception réseau sur HTTP | Position réseau, cookie sans Secure | Secure + HSTS | CVE-2024-28892 (Netdata) |
| Tossing de cookie depuis sous-domaine | Prise de contrôle de sous-domaine, Domain= avec point | Préfixe __Host- | HackerOne #1234231 |
| Injection CORS | Mauvaise configuration CORS autorisant Set-Cookie | SameSite=Strict | OWASP OTG-SESS-003 |
CVE-2024-28892 — Netdata Cloud, attribut Secure manquant (CVSS 6.5)
Les cookies de session de Netdata Cloud étaient transmis sans l'attribut Secure. Sur des réseaux d'entreprise avec inspection TLS ou des réseaux publics (hôtels, aéroports), un attaquant pouvait observer ou injecter le cookie en clair. Corrigé en imposant Secure et en ajoutant Strict-Transport-Security: max-age=63072000; includeSubDomains.
HackerOne #1629543 — Fixation de session OAuth2 GitLab (3 000 $)
GitLab ne renouvelait pas l'identifiant de session après l'échange du code OAuth2. Un XSS sur sous-domaine permettait un tossing de cookie de session pour le domaine parent gitlab.com. Lors de l'authentification via Google SSO, la session non-renouvelée devenait pleinement authentifiée. La gravité a été escaladée à Haute en raison de l'accessibilité des comptes administrateur.
HackerOne #1234231 — Tossing de cookie de sous-domaine Auth0
Une application utilisant Auth0 avec la configuration Domain=.app.example.com était exposée quand un attaquant découvrit un sous-domaine abandonné pointant vers un service hors service. Depuis le sous-domaine pris en contrôle, l'attaquant émettait Set-Cookie: auth_session=CONNU; Domain=.app.example.com. Après authentification des utilisateurs sur le locataire principal, la session non-renouvelée donnait à l'attaquant un accès complet.
Set-Cookie sur la page de connexion — notez le nom et la valeur courante du cookie de session.document.cookie dans la console du navigateur — si le cookie de session apparaît, il peut être défini via XSS.Secure : inspectez Set-Cookie. Un Secure manquant sur une application HTTPS est une vulnérabilité indépendante (CWE-614).Domain : un point initial Domain=.example.com signale un risque de tossing de cookie.# nuclei — vérifications d'attributs de cookie
nuclei -u https://cible.com -t http/misconfiguration/cookies/cookie-without-httponly.yaml
nuclei -u https://cible.com -t http/misconfiguration/cookies/cookie-without-secure.yaml
nuclei -u https://cible.com -t http/misconfiguration/cookies/cookie-without-samesite.yaml
# subzy pour les candidats à la prise de contrôle de sous-domaine
subzy run --targets sous-domaines.txt --concurrency 100BreachVex détecte la fixation de session par cookie en : auditant tous les attributs Set-Cookie selon les exigences OWASP ASVS V3.4, tentant de rejouer le cookie de session pré-auth à travers le point de terminaison de connexion, et comparant les valeurs post-auth. Une valeur correspondante déclenche un signalement CWE-384 ÉLEVÉ.
<?php
// PHP — correction complète
session_start();
if (authenticate($_POST['email'], $_POST['password'])) {
session_regenerate_id(true); // true : supprimer l'ancien fichier de session
$_SESSION['user_id'] = $user_id;
}
// php.ini — bloquer toute livraison de session non-cookie
session.use_only_cookies = 1
session.cookie_httponly = 1
session.cookie_secure = 1
session.cookie_samesite = "Strict"
session.use_strict_mode = 1# FastAPI — cookie de session avec préfixe __Host- (protection maximale)
response.set_cookie(
key="__Host-session",
value=nouveau_jeton_session,
httponly=True,
secure=True,
samesite="strict",
max_age=3600,
path="/",
# domain= DOIT être omis pour que le préfixe __Host- soit valide
)Strict-Transport-Security: max-age=63072000; includeSubDomains; preloadincludeSubDomains empêche la rétrogradation HTTP sur tout sous-domaine, bloquant le vecteur d'injection de cookie par interception réseau. Sans includeSubDomains, une interception réseau sur static.example.com en HTTP peut injecter des cookies pour example.com.
Le préfixe de cookie __Host- élimine le tossing de sous-domaine, la livraison HTTP par interception réseau, et l'injection de cookie avec scope Domain en un seul changement de configuration. C'est la protection la plus forte disponible imposée par le navigateur contre la livraison de fixation par cookie. La seule restriction : les applications servies depuis un chemin non-racine (ex. /app/) ne peuvent pas utiliser __Host- car il exige Path=/.
La fixation de session par cookie se produit quand un attaquant plante un cookie de session avec une valeur connue dans le navigateur de la victime avant sa connexion. Cela peut être fait via XSS, interception réseau sur des pages non-HTTPS, ou injection de cookie depuis un sous-domaine. Si l'application ne régénère pas l'identifiant de session à la connexion, la valeur connue de l'attaquant devient un identifiant de session authentifié.
Une vulnérabilité XSS stockée sur n'importe quelle page de la même origine permet à un attaquant d'injecter du JavaScript qui définit un cookie de session. Quand la victime visite la page infectée avant de se connecter, son navigateur a désormais l'identifiant choisi par l'attaquant. Si le serveur ne renouvelle pas cet identifiant à l'authentification, la fixation est complète. HttpOnly empêche JavaScript de lire les cookies mais ne l'empêche pas de définir des cookies sans HttpOnly.
HttpOnly empêche JavaScript de définir le cookie de session. Secure empêche la livraison sur HTTP (interception sur du trafic en clair). SameSite=Strict empêche la livraison de cookie inter-sites. Le préfixe __Host- empêche la livraison depuis des sous-domaines en exigeant que le cookie ne soit défini que par l'hôte exact. Les quatre ensemble fournissent une défense en profondeur contre les vecteurs de livraison par cookie.
Le préfixe __Host- (RFC 6265bis) impose : attribut Secure obligatoire, pas d'attribut Domain (liaison à l'hôte), Path=/ obligatoire. Les navigateurs rejettent les en-têtes Set-Cookie pour les cookies __Host- qui violent ces contraintes. Un cookie nommé __Host-session ne peut pas être défini par sub.example.com pour example.com — éliminant entièrement la livraison de fixation inter-sous-domaines. Spring Security 5.8+, Rack 3+ et Django 4.2+ prennent nativement en charge ce préfixe.
Oui, sur des connexions non-HTTPS ou des pages avec du contenu mixte. L'attaquant intercepte la réponse HTTP et injecte un en-tête Set-Cookie. L'attribut Secure l'empêche sur HTTPS. HSTS (Strict-Transport-Security: includeSubDomains) empêche la connexion HTTP initiale permettant l'interception.
Le cookie tossing est une technique où un sous-domaine définit un cookie avec Domain=.example.com, causant l'envoi de ce cookie par le navigateur au domaine parent. Si l'attaquant contrôle un sous-domaine via une prise de contrôle de sous-domaine, il peut envoyer un cookie de session connu à la page de connexion de l'application principale, permettant la fixation de session. Le préfixe __Host- l'empêche en interdisant l'attribut Domain.
La ChangeSessionIdAuthenticationStrategy par défaut de Spring Security (depuis 3.2) appelle HttpServletRequest.changeSessionId() lors d'une authentification réussie. Les applications qui la surchargent avec sessionManagement().sessionFixation().none() désactivent la protection. La configuration correcte est la valeur par défaut : sessionManagement().sessionFixation().changeSessionId().
CVE-2024-28892 dans Netdata Cloud exposait des cookies de session sans l'attribut Secure sur des pages avec contenu mixte. Un attaquant sur le même segment réseau pouvait intercepter la requête HTTP et observer ou injecter le cookie de session, permettant la livraison de fixation par interception réseau. Corrigé en imposant Secure sur tous les cookies de session et en ajoutant des en-têtes HSTS.
Non. Les cookies HttpOnly ne peuvent pas être définis ou modifiés via document.cookie. Un attaquant a besoin d'un vecteur de livraison différent : interception réseau (injection de Set-Cookie dans une réponse HTTP), injection de cookie depuis un sous-domaine (Set-Cookie avec attribut Domain=), ou une vulnérabilité côté serveur. HttpOnly est essentiel mais ne protège pas contre l'injection au niveau réseau ou sous-domaine.
Les cookies avec SameSite=None sont envoyés dans les requêtes inter-sites et peuvent être définis par des réponses inter-sites. Cette configuration est nécessaire pour des cas d'utilisation légitimes de tiers (widgets de paiement, SSO intégrés) mais crée une surface de livraison pour la fixation de session si combinée avec un cookie de session. Les cookies de session doivent utiliser SameSite=Strict ou au minimum SameSite=Lax.