Les alias d'hôtes API peuvent-ils contourner votre examen de destination ?
Les alias d'hôtes API peuvent masquer des destinations non examinées. Découvrez comment inventorier les CNAME et URL de base, lier les identifiants à l'autorité et éviter les fuites par redirection.

Un examen de destination n'a de valeur que s'il porte sur le nom qui reçoit l'identifiant. Si une équipe approuve https://api.example.test tout en laissant les agents utiliser https://api-us.example.test, https://gateway.example.test ou un point de compatibilité fourni par le fournisseur, l'approbation décrit une intention plutôt qu'une limite.
J'ai vu cela échouer de la manière la plus banale possible : quelqu'un approuve un nom d'hôte familier, une variable de déploiement pointe vers un alias régional et le même jeton porteur fonctionne. Nul besoin d'une exploitation spectaculaire. L'équipe avait simplement plus de noms de destination que son processus d'examen ne l'admettait.
La première correction est conceptuelle. Un enregistrement CNAME, une URL de base alternative, une redirection, une adresse IP et une autorité HTTP sont liés, mais ne sont pas interchangeables. Les traiter comme une seule et même chose donne des examens qui semblent rigoureux et des contrôles qui laissent fuir les identifiants.
Un examen de destination ne couvre que l'hôte littéral
L'examen de api.example.test n'approuve pas api-eu.example.test, proxy.example.test ni api.example.test.evil.invalid. L'identifiant ne doit aller qu'à un nom d'hôte exact et normalisé, figurant dans un inventaire explicite pour cet identifiant.
Les équipes partent souvent d'une règle informelle, par exemple « ce jeton sert à l'API d'Example ». C'est une affirmation de propriété, pas une règle de destination. Une entreprise peut exploiter de nombreux domaines, un fournisseur peut faire passer le trafic derrière plusieurs noms et un tiers peut héberger une partie de la périphérie du fournisseur. Le client HTTP a besoin d'une URL précise. Votre contrôle aussi.
Formulez la limite avec des éléments qu'un analyseur d'URL peut comparer :
- schéma : généralement
https - nom d'hôte : nom d'hôte ASCII en minuscules après traitement IDNA
- port : le port explicite, ou celui par défaut du schéma
- règle de chemin : seulement si l'identifiant se limite à une surface API précise
Ne remplacez pas la liste de noms d'hôtes par un test de suffixe. endsWith("example.test") accepte notexample.test. endsWith(".example.test") accepte encore tous les sous-domaines actuels et futurs. Cela peut convenir à un maillage de services interne avec un seul propriétaire et de solides contrôles d'émission. Pour un identifiant qui peut modifier des données de production, c'est généralement une facilité dangereuse.
La question délicate est de savoir si une personne doit approuver chaque nom d'hôte avant son utilisation. Pour un jeton très privilégié, oui. Pour un jeton à faible périmètre utilisé auprès d'un fournisseur qui publie de nombreux points régionaux, approuvez une liste entretenue et faites de tout ajout un changement délibéré. Le coût d'un examen supplémentaire est inférieur à celui d'expliquer pourquoi un jeton a atteint un nom d'hôte que personne n'avait consigné.
Cela sépare aussi le contrôle de destination de l'examen du contenu de la requête. Un examinateur peut accepter un GET vers un hôte approuvé et refuser un POST qui modifie la facturation. Ce sont deux questions distinctes. Ne prétendez pas qu'une vérification du nom d'hôte décide si la requête est sûre : elle décide où l'identifiant peut aller.
Les CNAME changent l'itinéraire, pas l'hôte HTTP
Un CNAME modifie la résolution DNS. Il ne réécrit pas, à lui seul, le nom d'hôte dans l'URL, l'en-tête HTTP Host ni l'indication de nom de serveur TLS qu'envoie un client HTTPS classique.
Supposons qu'un agent appelle cette URL :
https://api.example.test/v1/orders
Le DNS peut répondre :
api.example.test. 300 IN CNAME api.edge.vendor.test.
api.edge.vendor.test. 300 IN A 203.0.113.42
La connexion TCP atteint 203.0.113.42, peut-être sur une infrastructure exploitée par le fournisseur. Le client doit tout de même demander api.example.test lors de TLS et envoyer Host: api.example.test. Si le serveur ne présente pas un certificat valide pour ce nom d'origine, la validation du certificat doit échouer. S'il en présente un, le serveur est autorisé à terminer le trafic pour ce nom, du moins à cet instant.
Cette distinction est importante, car elle écarte une correction populaire mais erronée : approuver la cible CNAME comme si elle était l'autorité API. Le nom cible est une preuve d'acheminement. Il peut vous aider à comprendre où va le trafic, mais il ne remplace pas l'examen du nom d'hôte de l'URL qui reçoit l'en-tête d'autorisation.
La RFC 1034 décrit un CNAME comme un alias d'un autre nom de domaine et impose de poursuivre la recherche au nom canonique. Cela explique le comportement du résolveur, pas une décision concernant un identifiant HTTP. Le DNS ne connaît ni jeton porteur, ni périmètre API, ni approbation de changement.
Un CNAME devient pertinent pour la sécurité dans quatre cas concrets :
- Le nom DNS appartient à une autre équipe ou à un fournisseur, donc une modification d'enregistrement peut changer l'endroit où se termine votre autorité approuvée.
- L'adresse résolue mène vers un réseau inattendu, comme une plage interne ou une adresse de métadonnées cloud.
- Un contrôle approuve des noms issus de la sortie DNS plutôt que l'autorité de l'URL, ce qui laisse une relation d'alias remplacer une véritable décision d'autorisation.
- L'application construit une seconde URL à partir du nom résolu, d'une cible de redirection ou d'un résultat de découverte de service, puis y transmet les identifiants.
Le quatrième cas divulgue des jetons. Les trois premiers affaiblissent l'examen et rendent une fuite ultérieure plus probable. Ils nécessitent des tests et des responsables différents.
Un CNAME ne vous protège pas non plus contre le rebinding DNS. Si un nom d'hôte autorisé par votre client se résout plus tard vers une autre adresse, le client peut ouvrir une nouvelle connexion vers cette adresse. Pour les destinations que vous contrôlez, surveillez les enregistrements et limitez les adresses auxquelles ils peuvent se résoudre. Pour celles que vous ne contrôlez pas, ne supposez pas qu'une résolution DNS unique prouve une sécurité durable.
Les URL de base alternatives créent le contournement le plus discret
Les URL de base alternatives sont le contournement le plus courant, car elles modifient directement l'autorité HTTP. Ce sont les noms cachés dans les variables d'environnement, les valeurs par défaut des SDK, les données de test et les notes de migration.
Un service peut documenter toutes ces URL pour des raisons légitimes :
https://api.example.test
https://api-us.example.test
https://sandbox-api.example.test
https://gateway.example.test/service-a
https://tenant-42.api.example.test
Elles peuvent aujourd'hui se terminer sur la même périphérie. Cela ne signifie pas qu'elles méritent le même identifiant. Le point de production peut accepter un jeton au niveau du compte, celui du bac à sable peut envoyer les requêtes vers un système distinct, le chemin de passerelle peut sélectionner un autre service et le nom d'hôte du locataire peut router selon l'identité du client. Les noms encodent des différences opérationnelles qu'une comparaison d'IP masque.
Le schéma d'échec est prévisible. Une base de code définit API_BASE_URL avec une valeur de production par défaut. Un développeur la modifie pour un test régional ou une migration. La couche qui injecte les identifiants voit une URL qui paraît encore liée et ajoute l'en-tête. L'examen de destination était attaché à une étiquette comme « API Example », pas à l'autorité exacte, donc personne ne voit l'élargissement.
Corrigez le modèle de données avant de corriger le code. Chaque identifiant a besoin de son propre enregistrement, avec quatre champs que les examinateurs peuvent inspecter :
credential: orders-write-prod
allowed authorities:
https://api.example.test:443
https://api-us.example.test:443
purpose: create and amend production orders
owner: commerce operations
review trigger: DNS change, new endpoint, scope change
Le mot « autorités » est choisi à dessein. Stockez ensemble le schéma, l'hôte et le port. Un nom d'hôte acceptable en HTTPS n'est pas automatiquement approuvé sur un port non standard. Un chemin peut compter lorsqu'une passerelle partagée utilise un hôte pour des API sans rapport, mais les règles de chemin demandent une normalisation rigoureuse et ne doivent jamais remplacer des identifiants séparés quand les périmètres diffèrent.
Ne vous appuyez pas sur la liste publiée par un fournisseur comme inventaire définitif. La documentation du fournisseur indique ce qui peut exister. Votre code et vos paramètres de déploiement indiquent ce que vous pouvez appeler. Il vous faut les deux, ainsi que les noms restés dans une automatisation ancienne après une migration.
L'audience de l'identifiant est la limite
La bonne question n'est pas « quels serveurs appartiennent à ce fournisseur ? ». C'est « quelles autorités HTTP peuvent recevoir ce secret précis dans ce chemin de requête précis ? ».
Un jeton porteur n'a aucune restriction d'audience intégrée, sauf si son émetteur l'applique. Dès qu'un client le place dans un en-tête Authorization, chaque destinataire qui reçoit l'en-tête peut tenter de l'utiliser. L'authentification Basic et les en-têtes de clé API personnalisés ont le même problème de transport. Le chiffrement en transit protège la requête pendant son acheminement, mais ne restreint pas l'audience au niveau applicatif.
Les jetons d'accès OAuth incluent parfois une revendication aud. Elle aide le serveur de ressources à refuser un jeton destiné à quelqu'un d'autre, mais ne confondez pas le refus côté serveur avec un comportement client sûr. Envoyer un jeton au mauvais nom d'hôte l'expose quand même à cet hôte et le place dans ses journaux d'accès, sa télémétrie ou sa file de traitement des incidents. Un jeton refusé vaut mieux qu'un jeton accepté, mais sa divulgation reste évitable.
La liaison d'identifiants comporte deux parties :
- Le client injecte l'identifiant uniquement pour une autorité examinée.
- L'émetteur de l'identifiant lui donne le périmètre, l'audience et l'environnement les plus restreints possibles.
Il vous faut les deux. La liaison à l'hôte évite qu'une erreur client disperse un secret parmi des services voisins. Le périmètre limite les dégâts si l'hôte attendu, ses journaux ou sa configuration de routage sont compromis.
C'est pourquoi une unique clé API à l'échelle de l'organisation est un si mauvais marché. Elle simplifie la mise en place et complique la réponse aux incidents. Si la même clé atteint une API de paiements, un collecteur analytique et une passerelle de préproduction, vous ne pouvez pas révoquer l'accès à une destination sans perturber les trois. Des identifiants distincts transforment une erreur de routage en rotation circonscrite, au lieu d'une panne qui mobilise tout le monde.
Inventoriez les noms dans le code, le DNS et la documentation du fournisseur
Un inventaire de points de terminaison devient crédible quand il saisit les usages observés plutôt que la seule architecture prévue. Construisez-le à partir du code, de la configuration de déploiement, du DNS et de la documentation du fournisseur, puis rapprochez les écarts.
Commencez par rechercher dans le dépôt les schémas d'URL et les paramètres d'URL de base. Incluez le code applicatif, les scripts shell, les définitions CI, les fichiers d'exemple, les définitions d'infrastructure et les données de test. Consignez chaque nom d'hôte, même ceux qui paraissent obsolètes. Les anciens noms restent dangereux lorsqu'une tâche cron ou une invite d'agent les appelle encore.
Résolvez ensuite chaque candidat dans le même contexte de résolveur que la machine appelante. Sur macOS ou un autre système Unix, une inspection de base ressemble à ceci :
dig +noall +answer api.example.test CNAME A AAAA
Un format de sortie utile est :
api.example.test. 300 IN CNAME api.edge.vendor.test.
api.edge.vendor.test. 60 IN A 203.0.113.42
api.edge.vendor.test. 60 IN AAAA 2001:db8::42
Lancez des requêtes séparées pour CNAME, A et AAAA si votre résolveur ne renvoie pas toute la chaîne dans une seule réponse. Consignez la date de requête et le résolveur utilisé, car le DNS à vues séparées peut donner des réponses différentes à un ordinateur portable, un exécuteur CI et un hôte de production. Ne copiez pas l'adresse IP obtenue dans une liste d'autorisation permanente pour une API Internet. Les périphéries changent régulièrement d'adresse. Conservez-la comme élément d'examen et alertez en cas de changements surprenants.
Créez ensuite une table d'inventaire avec une ligne par autorité, et non une ligne par fournisseur. Elle doit répondre à ces questions sans réunion :
| Autorité | Utilisée par | Identifiant | Propriétaire DNS | Itinéraire attendu | État de l'examen |
|---|---|---|---|---|---|
https://api.example.test:443 | agent de production | orders-write-prod | fournisseur | périphérie publique | approuvé |
https://api-us.example.test:443 | tâche régionale | orders-write-us | fournisseur | périphérie publique | en attente |
https://gateway.example.test:443 | script historique | aucun | équipe interne | passerelle interne | retiré |
N'inventez pas de ligne simplement parce qu'un fournisseur propose un point de terminaison. Marquez-le comme inutilisé tant qu'un code, une configuration ou une migration approuvée ne le nécessite pas. L'inventaire doit rendre visible une capacité accidentelle, pas documenter toutes les possibilités.
La fiche OWASP de prévention du Server-Side Request Forgery fait un constat lié : lorsqu'une application ne parle qu'à des applications de confiance identifiées, une liste d'autorisation est viable, mais la validation de domaine seule ne règle pas le comportement DNS. Ces conseils visent les SSRF, mais la leçon opérationnelle s'applique ici. Une liste de noms d'hôtes n'est solide que si vous savez qui maintient ces noms, vers quoi ils se résolvent et si un appelant peut transformer plus tard un nom examiné en une autre requête.
Les redirections doivent faire l'objet de leur propre examen
Une redirection est une nouvelle décision de destination. Un client qui suit automatiquement les redirections peut quitter une autorité approuvée après la première requête, et un en-tête d'autorisation ne doit pas l'accompagner.
Pour les appels API avec identifiants, commencez avec les redirections désactivées. Traitez une réponse 301, 302, 303, 307 ou 308 comme une réponse qui exige une décision explicite. Si la nouvelle URL figure déjà dans la liste exacte des autorités de l'identifiant et que le comportement de la méthode et du corps est acceptable, effectuez une requête distincte vers elle. Si elle n'est pas répertoriée, arrêtez-vous.
Les codes d'état ne sont pas interchangeables. Un 303 transforme souvent une requête en GET ; les 307 et 308 préservent la méthode et le corps de requête. La répétition automatique d'un POST avec un en-tête d'autorisation a plus de conséquences qu'un GET qui paraît inoffensif, surtout lorsque le nouvel hôte diffère.
Testez le comportement de la bibliothèque HTTP précise que vous utilisez. Certains clients retirent les en-têtes sensibles lors d'un changement d'hôte, d'autres les conservent dans des conditions inattendues, et des enveloppes peuvent remplacer les valeurs par défaut. Un test doit capturer la requête reçue par un second hôte contrôlé, puis vérifier qu'il n'a reçu ni l'identifiant ni une copie du corps. Le nom d'une bibliothèque ne prouve pas sa règle de redirection.
Un chemin d'appel sûr est simple à décrire :
1. Parse the requested URL.
2. Normalize and match its authority against the credential record.
3. Inject the credential only after that match.
4. Send one request with redirects disabled.
5. If a redirect arrives, parse and review the new authority before any new request.
Cette séquence protège aussi contre un bug plus subtil : injecter l'en-tête dans un client générique avant de vérifier la destination. Dès que le code attache un jeton à un objet de requête réutilisable, les changements d'URL ultérieurs peuvent l'emporter vers une destination imprévue. Liez les identifiants au dernier moment raisonnable, après avoir déterminé l'URL finale.
Les noms d'hôtes partagés exigent des identifiants séparés
Un seul nom d'hôte peut héberger plusieurs API, environnements et locataires. La correspondance exacte de l'hôte est nécessaire, mais elle ne peut pas exprimer toutes les différences de sécurité derrière une passerelle partagée.
Prenons https://gateway.example.test. Un chemin peut créer des factures, un autre transmettre de la télémétrie et un troisième administrer des utilisateurs. Si un jeton porteur autorise les trois, l'examen de l'hôte ne fournit qu'une protection grossière. Un bug qui remplace /telemetry par /admin reste sur le nom d'hôte approuvé et réussit tout de même.
La bonne réponse consiste généralement à utiliser des identifiants séparés, avec des périmètres distincts. Donnez au client de télémétrie un jeton incapable d'administrer les utilisateurs, même si les deux appels vont vers le même hôte. Si le fournisseur propose des audiences ou des indicateurs de ressource, utilisez-les. S'il ne propose que des jetons étendus, séparez les comptes de service ou choisissez une limite d'intégration plus sûre plutôt que de prétendre qu'une liste de chemins autorisés règle l'autorisation.
Les règles de chemin ont tout de même leur place. Elles peuvent détecter des erreurs de programmation et rendre l'intention vérifiable. Les chemins sont toutefois plus faciles à mal gérer que les hôtes : encodage en pourcentage, barres obliques répétées, segments par points, réécritures de passerelle et redirections de version compliquent tous la comparaison. Normalisez avec le même analyseur d'URL et la même bibliothèque de requêtes que ceux qui envoient l'appel. Ne prenez jamais une décision de sécurité avec une vérification de sous-chaîne écrite à la main.
Le même raisonnement vaut pour les ports. api.example.test:443 et api.example.test:8443 sont des autorités différentes. Un proxy inverse peut les router vers des services différents, et un développeur qui teste le second port peut croire que le premier examen le couvre. Consignez les deux ou n'autorisez aucun des deux.
Placez les approbations là où une personne peut encore juger la destination
Une approbation qui dit seulement « autoriser l'appel API » demande à l'examinateur de signer un chèque en blanc. L'invite doit indiquer la méthode, l'autorité complète normalisée, le chemin de requête, l'identité de l'identifiant et le processus demandeur. Sans cela, une personne n'a aucun moyen pratique de remarquer que l'agent est passé de l'API de production à un ancien nom d'hôte de compatibilité.
Sallyport conserve l'identifiant dans son coffre chiffré et effectue l'action HTTP au lieu de remettre le secret à l'agent. C'est utile, car l'approbation peut se situer à la frontière de l'action, où la destination et le processus demandeur sont visibles ensemble.
Ne transformez pas un écran d'approbation en rituel. L'approbation par session convient à une exécution d'agent connue et brève qui appelle un ensemble stable d'autorités approuvées. Exigez une confirmation par appel pour les identifiants capables de déplacer de l'argent, de supprimer des données ou d'atteindre des points d'administration. La friction doit suivre la conséquence d'un mauvais appel, pas la patience de l'examinateur.
Sallyport n'a volontairement ni langage de politique ni moteur de règles. Il ne faut donc pas le considérer comme un prétexte pour ignorer l'inventaire des points de terminaison. Sa porte de coffre et ses contrôles d'autorisation répondent à la question de savoir si un processus peut utiliser un identifiant maintenant. Votre enregistrement d'identifiant doit toujours répondre à la question de savoir quelle autorité a le droit de le recevoir.
Les journaux d'activité doivent conserver assez d'éléments pour reconstituer plus tard la décision : autorité demandée, itinéraire résolu lorsqu'il est disponible, méthode, état, session demandeuse et enregistrement d'identifiant appliqué. Ne consignez pas le secret ni les charges utiles sensibles complètes seulement pour améliorer la piste d'audit. Un journal qui crée un second dépôt de secrets n'améliore pas l'audit.
Réexaminez les alias après chaque changement DNS et d'intégration
La liaison de destination se dégrade lorsque le DNS, les points de terminaison du fournisseur ou les paramètres de déploiement changent. Faites de l'examen de l'inventaire une partie de ces changements, plutôt qu'un exercice annuel qui découvre une accumulation de noms obsolètes.
Déclenchez un examen lorsqu'une personne ajoute ou modifie un CNAME, change un enregistrement A ou AAAA pour un nom interne autorisé, introduit un point de terminaison régional, remplace un SDK, modifie une passerelle API ou ajoute une redirection. L'examinateur doit comparer les anciennes et nouvelles listes d'autorités, puis décider si l'identifiant existant peut suivre le changement. Les changements de propriété DNS méritent la même attention que les changements de propriété du code.
Pour les noms que vous contrôlez, alertez lorsqu'un nom d'hôte approuvé commence à se résoudre vers des adresses privées, de bouclage, locales au lien ou internes inattendues. C'est une défense contre les SSRF autant qu'une défense des identifiants. Pour les noms publics de fournisseurs, alertez sur les changements de cible CNAME et les changements importants de plages d'adresses, puis enquêtez au lieu de bloquer automatiquement chaque rotation de CDN.
Conservez un petit test de régression à côté de l'intégration. Il doit essayer une URL approuvée, une URL de base alternative absente de la liste, un hôte au suffixe trompeur, un port alternatif explicite et une redirection vers un autre hôte. Le résultat attendu n'est pas seulement un échec de connexion réseau. Le client doit refuser d'attacher l'identifiant avant qu'une requête n'atteigne la destination absente de la liste.
C'est cette dernière condition qui doit faire référence. Si l'agent peut envoyer le secret d'abord et découvrir ensuite que la destination était mauvaise, l'examen a échoué au moment où il comptait.
FAQ
Un CNAME change-t-il l'hôte qui reçoit un jeton API ?
Un CNAME associe un nom DNS à un autre pendant la résolution. Le client peut toujours envoyer le nom d'hôte de l'URL d'origine dans l'en-tête HTTP Host et le SNI TLS. La cible du CNAME n'est donc pas automatiquement l'autorité de destination HTTP.
Les alias CNAME d'API sont-ils dangereux ?
Non. Un alias n'est pas dangereux en soi et de nombreux fournisseurs l'utilisent pour gérer le trafic. Le risque apparaît lorsqu'un examinateur approuve un identifiant pour un nom alors que le client peut l'envoyer via une autre URL de base apparemment approuvée, ou lorsque la propriété DNS peut changer sans examen.
Comment limiter un identifiant API aux hôtes approuvés ?
Utilisez une liste exacte de noms d'hôtes pour chaque identifiant, puis comparez-y chaque URL de base configurée. N'acceptez pas un domaine parent, une correspondance de suffixe ou une plage d'adresses IP à la place de cette liste.
Quels hôtes doivent figurer dans un inventaire de points de terminaison API ?
Répertoriez séparément les points de terminaison de production, de bac à sable, régionaux, locataires, historiques, proxy et privés. Examinez ensuite les fichiers de configuration, variables de déploiement, documents du fournisseur, enregistrements DNS et comportements de redirection HTTP pour trouver les noms réellement utilisés.
Une redirection HTTP peut-elle divulguer un jeton porteur à un autre hôte ?
Une redirection peut changer l'autorité de l'URL après la première requête. Un client sûr retire les en-têtes sensibles avant une redirection vers un autre hôte, mais vous devriez désactiver les redirections automatiques pour les requêtes avec identifiants, sauf si vous examinez explicitement chaque saut.
La validation des certificats TLS suffit-elle pour examiner une destination API ?
Non. Un certificat prouve que le serveur contrôle un nom au moment de la connexion. Il ne dit pas si ce nom doit recevoir un identifiant particulier ni si son enregistrement DNS pointera plus tard ailleurs.
Plusieurs services doivent-ils partager une même clé API sur le même domaine ?
Les passerelles partagées nécessitent des identifiants distincts par service et environnement dès que les périmètres d'autorisation diffèrent. Une liste d'hôtes autorisés ne peut pas corriger un jeton qui donne à chaque charge de travail accès au même compte trop étendu.
Faut-il examiner les noms DNS ou les adresses IP pour l'accès API ?
Examinez d'abord l'autorité de l'URL, puis résolvez les enregistrements A, AAAA et CNAME pour comprendre l'itinéraire. Réexaminez les deux lors d'un changement DNS, d'une migration de fournisseur ou de la mise en service d'un nouveau point régional.
Pourquoi *.example.com est-il une mauvaise liste d'autorisation de destinations API ?
Non. Les hôtes exacts autorisent un nom prévu comme api.example.com, tandis qu'un caractère générique admet aussi dev.api.example.com, old.api.example.com et tout futur nom sous cette zone. Ces noms ont souvent des propriétaires et des contrôles différents.
Comment tester si un agent peut contourner l'approbation de destination ?
Le test utile consiste à vérifier si l'agent peut appeler avec un identifiant un hôte absent de la liste, suivre une redirection vers cet hôte ou utiliser une URL de base non répertoriée. Si oui, l'examen consigne une intention sans l'appliquer.