Denial of wallet sur une application adossée à une API d’IA
Section intitulée « Denial of wallet sur une application adossée à une API d’IA »Le denial of wallet (déni de portefeuille) vise la facture plutôt que la disponibilité : un attaquant fait consommer à une application des appels payants vers une API (Application Programming Interface) d’IA (intelligence artificielle) générative jusqu’à épuiser le budget ou déclencher un plafond qui coupe le service. Le coût étant facturé à l’usage, chaque requête abusive se paie en euros, pas seulement en ressources. La position défendue : le quota se compte en jetons consommés par identité, jamais en nombre de requêtes seul.
C’est comme un buffet à volonté payé par l’organisateur à chaque assiette servie. Un petit malin qui revient cent fois avec des assiettes énormes ne casse rien, mais il vide le budget de la soirée. Le but est de limiter les assiettes de chacun sans fermer le buffet.
→ Lire l’explication complète de la marmotte
Mécanique de coût d’une API d’IA générative
Section intitulée « Mécanique de coût d’une API d’IA générative »Le fournisseur facture en jetons (tokens) : des fragments de texte comptés à l’entrée (le prompt, l’historique, les documents joints) et à la sortie (la réponse générée), avec un tarif de sortie généralement plus élevé que celui d’entrée, et un tarif très variable d’un modèle à l’autre. Conséquence directe : deux requêtes HTTP (HyperText Transfer Protocol) identiques en apparence peuvent différer de plusieurs ordres de grandeur en coût. Un limiteur qui compte des requêtes par minute protège le serveur, pas le budget.
Les leviers d’un attaquant découlent de cette tarification :
- Gonfler l’entrée : envoyer des documents au maximum de la fenêtre de contexte à chaque appel.
- Forcer une sortie longue : demander une énumération, une traduction intégrale, une répétition sans fin, pour que la génération s’arrête au plafond de sortie plutôt que naturellement.
- Choisir le modèle : si le client transmet le nom du modèle et que le serveur le relaie, l’attaquant sélectionne le plus cher.
- Déclencher des boucles : dans une application agentique, une instruction injectée peut provoquer des appels d’outils en chaîne, chacun renvoyant son résultat dans le contexte de l’appel suivant, donc un coût d’entrée qui croît à chaque tour.
- Multiplier les identités : ouvrir des comptes gratuits en série quand l’inscription ne coûte rien.
La slide commerciale parle d’« IA à la demande ». Personne ne précise à la demande de qui.
Quotas par utilisateur et plafonds de dépense
Section intitulée « Quotas par utilisateur et plafonds de dépense »Les contrôles efficaces s’empilent en couches, du plus proche de la requête au plus global.
Bornes par requête, fixées côté serveur. Taille maximale d’entrée, plafond de jetons de sortie (paramètre de type max_tokens selon l’API), modèle imposé par le serveur et jamais lu depuis la requête cliente, nombre maximal d’itérations pour une boucle d’agent. Ces bornes coûtent zéro et suppriment les attaques les plus rentables. Une application qui n’a pas de plafond de sortie laisse l’attaquant fixer la facture.
Budget de jetons par identité. Un compteur par utilisateur ou par locataire, sur une fenêtre glissante (heure, jour), incrémenté avec la consommation réelle renvoyée par le fournisseur dans chaque réponse. Au dépassement, refus explicite ou bascule vers un modèle moins coûteux. Ce budget suppose une identité stable : pour un usage anonyme, il ne reste que l’adresse source, trivialement multipliée ; d’où l’intérêt d’exiger une authentification avant tout appel payant. Le rattachement fiable des requêtes à une identité relève de la rubrique identités.
Plafond global chez le fournisseur. Les consoles des fournisseurs proposent des seuils d’alerte et, selon les offres, des plafonds de dépense. Le comportement au dépassement (blocage immédiat, alerte seule, délai de prise en compte) varie et se vérifie dans les conditions en vigueur. Ce plafond est le dernier filet, pas un contrôle : quand il se déclenche, l’attaquant a obtenu exactement ce qu’il voulait, soit la facture, soit l’indisponibilité pour tout le monde.
Le compromis central est là : un plafond global bas protège le budget au prix d’une coupure totale, un plafond haut garde le service au prix de la facture. Les budgets par identité rendent ce dilemme rare, en arrêtant l’abus avant qu’il atteigne le plafond global.
Exemple : limites de débit par jeton client dans nginx
Section intitulée « Exemple : limites de débit par jeton client dans nginx »Cet extrait protège l’entrée d’une passerelle interne qui relaie les appels vers le fournisseur. Il ne compte pas les jetons consommés (cette logique vit dans la passerelle, qui lit la consommation renvoyée par le fournisseur), mais il borne la taille, le débit et la concurrence avant tout appel payant.
# Contexte http de nginx.conf# Clé de limitation : l'en-tête Authorization, disponible avant la phase d'accès.# Une variable posée par auth_request serait encore vide ici, car limit_req# s'exécute en phase preaccess, avant auth_request (phase access).limit_req_zone $http_authorization zone=ia_debit:10m rate=20r/m;limit_conn_zone $http_authorization zone=ia_conc:10m;# Disjoncteur global : borne le débit total vers le fournisseur, toutes identités confondueslimit_req_zone $server_name zone=ia_global:1m rate=300r/m;
server { listen 443 ssl; server_name passerelle-ia.interne.example; ssl_certificate /etc/nginx/tls/passerelle-ia.crt; ssl_certificate_key /etc/nginx/tls/passerelle-ia.key;
location /v1/ { client_max_body_size 64k; # borne la taille d'entrée, donc les jetons d'entrée limit_req zone=ia_debit burst=5 nodelay; limit_req zone=ia_global burst=50; limit_conn ia_conc 2; # deux générations simultanées par jeton limit_req_status 429; limit_conn_status 429;
auth_request /verif-jeton; # jeton invalide : refus, aucun appel payant proxy_read_timeout 60s; # coupe les générations interminables proxy_pass http://passerelle_ia_amont; }
location = /verif-jeton { internal; proxy_pass http://fournisseur-identite.interne.example/introspection; proxy_pass_request_body off; proxy_set_header Content-Length ""; }}Un attaquant qui fait varier l’en-tête Authorization contourne la limite de débit, mais chaque jeton inventé échoue à auth_request et n’atteint jamais le fournisseur : la limite protège le coût, qui est ce qui compte ici. Le disjoncteur global, lui, borne le pire cas quelle que soit la stratégie.
Détection du denial of wallet
Section intitulée « Détection du denial of wallet »Les budgets arrêtent l’abus attendu ; la détection repère celui qui passe sous les seuils. Signaux à suivre, par identité et au global :
- coût par requête anormalement élevé, et surtout ratio sortie sur entrée qui dérive vers le plafond de sortie à chaque appel ;
- taux élevé de réponses arrêtées par la limite de longueur plutôt que terminées naturellement (le motif d’arrêt figure dans la réponse de la plupart des API) ;
- concentration : une poignée d’identités qui consomment l’essentiel du budget ;
- rafales d’inscriptions suivies d’une consommation maximale sur chaque compte.
Ces métriques se collectent dans la passerelle et s’exploitent avec les outils décrits dans observer un modèle de langage en production. Le point faible classique : l’alerte de facturation du fournisseur arrive avec plusieurs heures de retard, donc la détection doit reposer sur les compteurs internes, pas sur la console du fournisseur.
Ce que ces limites ne garantissent pas
Section intitulée « Ce que ces limites ne garantissent pas »Les quotas ne distinguent pas un utilisateur légitime intensif d’un compte compromis qui consomme dans son budget : c’est la détection d’anomalie qui fait la différence. Ils ne protègent pas non plus contre une clé du fournisseur volée et utilisée hors de la passerelle, sujet distinct traité dans la page sur les clés d’API de la rubrique IA. Enfin, un budget par identité ne vaut que ce que vaut le coût d’obtention d’une identité : une inscription gratuite sans vérification transforme le quota individuel en quota infini.
🐝 Ce qui arrive si on s’en passe
Section intitulée « 🐝 Ce qui arrive si on s’en passe »Sans budget par identité ni plafond de sortie, le seul contrôle restant est le plafond global du fournisseur : quand l’abus l’atteint, l’API refuse les appels de tous les utilisateurs à la fois, et le service reste coupé jusqu’au relèvement du plafond ou au début de la période de facturation suivante. Sans compteur interne, l’enquête ne dispose que de la facture agrégée par clé, qui ne permet ni d’identifier les comptes abusifs ni de les bloquer sélectivement. Sur une offre gratuite, chaque compte créé en série devient une consommation facturée sans aucune recette en face.
🦫 Explication de la marmotte 🍫
Section intitulée « 🦫 Explication de la marmotte 🍫 »Certaines applications utilisent un service d’intelligence artificielle payant, facturé selon la quantité de texte lue et écrite. Le texte est découpé en petits morceaux appelés jetons, et chaque jeton coûte un peu d’argent. Une personne malveillante peut profiter de ce système : elle envoie des textes très longs, demande des réponses sans fin, ou choisit le modèle le plus cher si l’application la laisse faire. Elle ne vole rien directement, mais elle fait grimper la facture de l’entreprise. Si l’entreprise a fixé un montant maximum chez le fournisseur, ce maximum est atteint et le service s’arrête pour tout le monde. Pour l’éviter, on met plusieurs barrières. D’abord, pour chaque demande, le serveur fixe lui-même une longueur maximale de texte envoyé et de réponse, et choisit le modèle. Ensuite, chaque utilisateur, identifié par son compte, reçoit un budget de jetons par heure ou par jour ; au-delà, ses demandes sont refusées. Le serveur limite aussi le nombre de demandes par minute et le nombre de demandes simultanées. Enfin, on surveille la consommation : un compte qui obtient toujours des réponses de longueur maximale ou qui dépense beaucoup plus que les autres doit être examiné. Ces barrières ne fonctionnent que si créer un compte n’est pas gratuit et instantané.
À lire aussi
- Relier FinOps et MLOps pour piloter le coût de l'IA en productionComment articuler FinOps et MLOps en IA pour attribuer, plafonner et contrôler le coût d'un modèle de l'entraînement à l'inférence, avec la surface d'attaque et les limites de l'approche.
- Mémoire persistante d'un assistant IA, empoisonnement et contrôleCe que la mémoire persistante d'un assistant d'intelligence artificielle public retient d'une conversation à l'autre, comment elle s'empoisonne et comment maîtriser son contenu.
- Rétention des données envoyées à une API d'IA générativeCe que devient une donnée envoyée à une API d'IA générative hébergée (rétention, entraînement, journaux d'abus, objets stockés) et comment le vérifier techniquement et contractuellement.
- Quotas cloud contre le déni de service par coûtGérer les quotas et limites de ressources cloud pour réduire le risque de déni de service par abus de facturation.
Pages voisines
La citent
- Comment fonctionne l'inférence d'un modèle de langage
- Différence entre IA et LLM : un champ entier, un type de modèle
- Evals LLM comment mesurer qu'un assistant IA répond juste
- Relier FinOps et MLOps pour piloter le coût de l'IA en production
- Quotas cloud contre le déni de service par coût
Denial of wallet sur une application adossée à une API d'IA
Elle cite
: les deux pages se citent l’une l’autre.
