Fixation de session par cookie (CWE-384) : un token connu planté via XSS avant connexion, puis réutilisé pour ouvrir la session authentifiée de la victime.
__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.
sequenceDiagram
participant A as Attaquant
participant V as Navigateur Victime
participant S as Serveur
Note over A,V: Phase de livraison (un vecteur parmi trois)
A->>V: "XSS document.cookie = session=ID_CONNU path=/"
Note over V: OU interception réseau injecte Set-Cookie sur HTTP
Note over V: OU sous-domaine définit Domain=.parent.com cookie
V->>S: "GET /login (Cookie session=ID_CONNU)"
S-->>V: "200 Page de connexion"
V->>S: "POST /login avec identifiants valides"
S-->>V: "302 /tableau-de-bord (session ID_CONNU NON renouvelé)"
A->>S: "GET /tableau-de-bord (Cookie session=ID_CONNU)"
S-->>A: "200 compte de la victime"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 | WiFi public ou proxy d'inspection TLS |
| 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 |
HackerOne #1629543 — Fixation de session OAuth2 GitLab
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().
Le cookie circule en clair sur HTTP : n'importe qui sur le chemin réseau peut le lire et, sur une page à contenu mixte, injecter un en-tête Set-Cookie avec la valeur de son choix. Cela suffit à livrer un identifiant de session connu avant la connexion. Imposer Secure sur tous les cookies de session et envoyer HSTS avec includeSubDomains ferme le vecteur de livraison ; seule la régénération de session à la connexion corrige la faille de fond.
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.