Fixation de session par meta refresh (CWE-384) : balises HTML ou liens injectés forcent la navigation vers une URL de login avec un token choisi par l'attaquant, sans JavaScript.
TL;DR
<meta http-equiv=refresh> pour rediriger les victimes vers des URL de connexion avec des identifiants choisis par l'attaquantscript-src qui bloque XSS mais pas les redirections HTML déclarativessession.use_only_cookies=1 (PHP), mode de suivi COOKIE (Java), session.use_strict_mode=1La fixation par meta refresh exploite la balise HTML <meta http-equiv="refresh"> pour rediriger silencieusement le navigateur de la victime vers une URL de connexion incluant un identifiant de session contrôlé par l'attaquant. Contrairement à la fixation par cookie basée sur XSS, la meta refresh ne nécessite aucune exécution JavaScript. C'est une redirection HTML déclarative — le navigateur la suit automatiquement, sans aucun clic au-delà de la visite initiale de la page.
L'attaque est particulièrement pertinente dans les contextes de sécurité où la CSP protège contre l'exécution de scripts mais pas contre les redirections déclaratives. Une application qui déploie une Content-Security-Policy: default-src 'self'; script-src 'nonce-...' stricte est immune au XSS réfléchi mais entièrement exposée à la fixation par meta refresh si elle affiche du contenu HTML contrôlé par l'utilisateur.
La page HTML malveillante hébergée par l'attaquant :
<!DOCTYPE html>
<html>
<head>
<!-- Délai zéro — la victime voit un flash avant la page de connexion -->
<meta http-equiv="refresh" content="0;url=https://cible.com/login?PHPSESSID=SID_ATTAQUANT_CHOISI">
<title>Chargement...</title>
</head>
<body>
<p>Redirection vers la connexion sécurisée...</p>
</body>
</html>Il n'y a pas de JavaScript. La balise <meta http-equiv="refresh"> oblige le navigateur à émettre une requête GET vers l'URL cible avec le paramètre de session. Le serveur, s'il accepte les identifiants de session par URL (comportement par défaut de PHP avec session.use_only_cookies = 0), stocke l'identifiant et attend qu'il soit authentifié.
Combinée avec une vulnérabilité de redirection ouverte sur le domaine cible, l'URL d'attaque semble légitime :
https://cible.com/redirect?url=https://attaquant.com/fixation.htmlLa victime voit une URL commençant par cible.com, clique dessus, est brièvement redirigée vers la page attaquant (la meta redirection se déclenche en quelques millisecondes), et atterrit sur la page de connexion avec l'identifiant fixé.
| Technique | Livraison | Visibilité victime | Prérequis |
|---|---|---|---|
| Page HTML meta refresh directe | E-mail / lien / QR code | Flash bref | Aucun (n'importe quelle origine) |
| Redirection ouverte + meta refresh | URL du domaine cible | Transparente | Redirection ouverte sur cible |
| Injection HTML dans contenu utilisateur | Stockée dans l'app | Invisible | Injection HTML dans l'app |
| Pièce jointe e-mail HTML | Fichier HTML joint à un e-mail | Onglet navigateur s'ouvre | E-mail ouvert dans le navigateur |
L'injection HTML dans le contenu utilisateur est la variante la plus furtive. Si une application web affiche du HTML fourni par l'utilisateur (éditeurs de texte enrichi avec désinfection insuffisante), un attaquant peut stocker une balise meta refresh dans sa bio de profil ou un commentaire.
<!-- L'attaquant stocke dans la bio de profil (injection HTML) -->
<meta http-equiv="refresh" content="0;url=https://cible.com/login?session=CONNU_ATTAQUANT">
<!-- Quand un admin ou utilisateur voit ce profil, il est redirigé silencieusement -->CVE-2024-38475 — Injection URL Apache httpd mod_rewrite (CVSS 9.1) Apache httpd 2.4.0 à 2.4.59 était vulnérable à l'injection URL via les règles mod_rewrite. Un attaquant pouvait construire des URL faisant rediriger mod_rewrite vers du contenu contrôlé par l'attaquant. Combiné avec la meta refresh, cette vulnérabilité permettait l'injection d'identifiant de session vers toute application derrière l'instance Apache affectée. Corrigé dans httpd 2.4.60.
Redirection ouverte dans redirect_uri OAuth — Pattern HackerOne courant
Les redirections ouvertes dans la validation de redirect_uri OAuth sont parmi les vulnérabilités les plus fréquemment signalées sur HackerOne (500 $ à 3 000 $). Combinées avec la meta refresh, une redirection ouverte devient un vecteur de livraison de fixation qui semble provenir du point de terminaison OAuth de confiance.
CVE-2024-47812 — Injection HTML Casdoor (CVSS 8.8) Casdoor avant 1.802.0 présentait plusieurs vulnérabilités dont une désinfection HTML insuffisante dans les champs d'affichage utilisateur. Une meta refresh injectée dans le nom d'affichage d'un utilisateur se déclenchait dans l'interface d'administration, livrant une fixation de session aux sessions administrateur.
Les applications qui affichent du HTML fourni par l'utilisateur (systèmes de tickets, éditeurs de texte enrichi, wikis internes, fonctionnalités d'aperçu d'e-mail) présentent un risque élevé d'injection meta refresh. Une balise meta refresh ne nécessite pas JavaScript et contourne toutes les politiques CSP script-src. Les désinfecteurs HTML doivent explicitement bloquer ou supprimer les balises meta — DOMPurify le fait par défaut, mais les désinfecteurs personnalisés et les listes blanches côté serveur l'oublient fréquemment.
<meta http-equiv="refresh" content="0;url=https://cible.com/login?PHPSESSID=TEST_META">. L'ouvrir dans un navigateur — confirmer la navigation automatique.PHPSESSID=TEST_META apparaît, la livraison de session par URL est activée.<meta http-equiv="refresh" content="0;url=https://collaborateur.net"> dans des champs HTML contrôlés par l'utilisateur. Vérifier Burp Collaborator pour les callbacks DNS/HTTP.?redirect=https://attaquant.com, ?next=//attaquant.com sur tous les paramètres de redirection.# Tester la livraison de session par paramètre URL
curl -c cookies.txt "https://cible.com/login?PHPSESSID=TEST_META_FIXATION"
grep "PHPSESSID=TEST_META_FIXATION" cookies.txt && echo "VULNÉRABLE : livraison de session par URL activée"
# nuclei — détection de redirection ouverte
nuclei -u https://cible.com -t http/misconfiguration/open-redirect.yaml
# Vérification des surfaces d'injection HTML
nuclei -u https://cible.com -t http/vulnerabilities/generic/html-injection.yaml; PHP — désactiver entièrement la livraison de session par URL
session.use_only_cookies = 1 ; rejeter les identifiants par URL
session.use_strict_mode = 1 ; rejeter les identifiants fournis externalement
session.cookie_samesite = "Lax"<!-- Java Servlet — mode de suivi COOKIE uniquement (Servlet 3.0+) -->
<web-app>
<session-config>
<tracking-mode>COOKIE</tracking-mode>
<!-- Supprime la prise en charge de la réécriture URL (;jsessionid=) -->
</session-config>
</web-app>Même si un identifiant de session livré par URL est accepté, la régénération à la connexion empêche la fixation :
# Rails — reset_session crée un nouvel identifiant même si une fixation a été livrée
def create
user = User.find_by(email: params[:email])
if user&.authenticate(params[:password])
reset_session # nouvel identifiant de session même si la fixation a été livrée
session[:user_id] = user.id
redirect_to dashboard_path
end
end# Django — régénération de session à la connexion
from django.contrib.auth import login
from django.contrib.sessions.backends.db import SessionStore
def login_view(request):
user = authenticate(request, username=request.POST['email'], password=request.POST['password'])
if user:
# cycle_key() génère un nouvel identifiant tout en préservant les données de session
request.session.cycle_key()
login(request, user)
return redirect('dashboard')# Python — equivalent DOMPurify avec bleach
import bleach
BALISES_AUTORISEES = ['p', 'b', 'i', 'em', 'strong', 'ul', 'ol', 'li', 'a', 'br']
# Note : 'meta' NE DOIT PAS figurer dans la liste des balises autorisées
def desinfection_html(input_utilisateur: str) -> str:
return bleach.clean(
input_utilisateur,
tags=BALISES_AUTORISEES,
attributes={'a': ['href', 'title']},
strip=True # strip, pas escape
)// JavaScript côté client — DOMPurify (bloque meta par défaut)
import DOMPurify from 'dompurify';
const propre = DOMPurify.sanitize(htmlUtilisateur, {
FORBID_TAGS: ['meta', 'link', 'base']
});La fixation par meta refresh et la fixation par paramètre URL sont la même attaque — la meta refresh est simplement un mécanisme de livraison pour les identifiants de session par paramètre URL. Désactiver la livraison de session par URL (session.use_only_cookies=1 en PHP, mode de suivi COOKIE en Java) élimine les deux vecteurs simultanément. La régénération de session à la connexion est toujours requise comme défense en profondeur.
La fixation par meta refresh utilise une page HTML avec une balise meta http-equiv=refresh pour forcer le navigateur de la victime à naviguer vers l'URL de connexion de l'application avec un identifiant de session choisi par l'attaquant dans la chaîne de requête. L'attaquant livre cette page HTML via e-mail, lien ou redirection ouverte. Quand la victime visite la page, son navigateur suit automatiquement la redirection meta avec le jeton de l'attaquant.
Les directives CSP script-src bloquent JavaScript mais ne bloquent pas les balises HTML meta refresh. La meta refresh est une redirection HTML déclarative — pas un script — donc les politiques strict-dynamic et default-src qui empêchent le XSS ne bloquent pas la livraison par meta refresh. Une page attaquant avec une meta refresh peut livrer une fixation de session même quand l'application cible a une CSP stricte.
Principaux vecteurs : (1) e-mail de hameçonnage avec corps HTML contenant une meta redirection, (2) page contrôlée par l'attaquant liée depuis les réseaux sociaux ou QR codes, (3) redirection ouverte sur le domaine cible pointant vers la page de l'attaquant, (4) injection HTML dans des champs contrôlés par l'utilisateur (éditeurs de texte enrichi, modèles d'e-mail). Le navigateur suit automatiquement la redirection — aucun clic n'est requis au-delà de la visite initiale.
Oui. Si l'application définit session.use_only_cookies=1 (PHP) ou le mode de suivi COOKIE (Java), elle ignore les identifiants de session dans les paramètres URL. La meta refresh redirige quand même le navigateur, mais le serveur rejette l'identifiant de session embarqué dans l'URL et en émet un nouveau. La fixation échoue car le serveur ne lie pas l'identifiant livré par URL à la session.
Une vulnérabilité de redirection ouverte sur le domaine cible (ex. /redirect?url=https://attaquant.com) permet à l'attaquant de lier les victimes à une page attaquant via une URL du domaine de confiance. La page attaquant contient une meta refresh pointant vers /login?JSESSIONID=CONNU. La victime voit une URL target.com, clique dessus, est brièvement envoyée vers attaquant.com (meta redirect se déclenche), et arrive sur la page de connexion avec l'identifiant fixé.
Les clients e-mail modernes (Gmail, Outlook) suppriment les balises meta refresh des corps HTML lors du rendu inline. Cependant, les pièces jointes HTML ouvertes dans un navigateur ne sont pas supprimées. Le hameçonnage via pièce jointe HTML est donc le principal vecteur de livraison par meta refresh — il contourne le filtrage e-mail car la meta redirection se déclenche dans le navigateur.
CVE-2024-38475 (Apache httpd mod_rewrite, CVSS 9.1) permettait l'injection de paramètres URL utilisables pour construire des chaînes de livraison meta refresh. Les chaînes SSRF vers injection HTML dans les systèmes de rendu de contenu (classe CVE-2024-32976) permettent également une livraison meta refresh vers les utilisateurs internes.
1. Créer une page HTML : <meta http-equiv=refresh content=0;url=https://cible.com/login?PHPSESSID=TEST_META>. 2. Héberger la page localement. 3. Visiter la page HTML dans le navigateur — vérifier la navigation vers l'URL de connexion avec le paramètre. 4. Authentifier via l'URL redirigée. 5. Comparer les jetons de session pré/post — une correspondance confirme la viabilité de la fixation par meta refresh.
Les désinfecteurs HTML qui mettent sur liste noire ou suppriment les balises meta empêchent l'injection dans les champs HTML contrôlés par l'utilisateur. DOMPurify bloque les balises meta par défaut. Les désinfecteurs côté serveur comme bleach (Python) nécessitent une liste blanche explicite des balises autorisées — meta ne doit jamais être dans la liste blanche. Les éditeurs de texte enrichi qui produisent du Markdown plutôt que du HTML brut sont immunisés.
La meta refresh est un vecteur de livraison pour la fixation par paramètre URL. La meta refresh redirige le navigateur vers une URL avec un paramètre de session — si le serveur accepte les sessions par URL (session.use_only_cookies=0 en PHP, réécriture URL en Java), la fixation réussit. Désactiver la livraison de session par URL élimine les deux vecteurs simultanément.