Les API sont devenues la colonne vertébrale des applications modernes (SaaS, mobiles, microservices). Elles exposent une surface d'attaque spécifique que le Top 10 web classique ne couvre pas suffisamment. En 2023, l'OWASP a mis à jour sa liste dédiée aux API pour refléter les risques réellement observés en production. Voici ce que contient cette liste : définition, exemple HTTP concret, remédiation et priorité de test pour chaque entrée.
Vue d'ensemble : les 10 risques en un coup d'œil
| ID | Nom | Impact principal | Priorité de test |
|---|---|---|---|
| API1 | Broken Object Level Authorization | Accès aux données d'autres utilisateurs | Critique |
| API2 | Broken Authentication | Usurpation de compte | Critique |
| API3 | Broken Object Property Level Authorization | Fuite de données, élévation de rôle | Haute |
| API4 | Unrestricted Resource Consumption | DoS applicatif, coûts cloud | Haute |
| API5 | Broken Function Level Authorization | Actions admin non autorisées | Critique |
| API6 | Unrestricted Access to Sensitive Business Flows | Abus métier, scraping, fraude | Moyenne |
| API7 | Server Side Request Forgery | Accès réseau interne, credentials cloud | Haute |
| API8 | Security Misconfiguration | Exposition de stack, données en clair | Haute |
| API9 | Improper Inventory Management | Endpoints legacy sans contrôles | Moyenne |
| API10 | Unsafe Consumption of APIs | Injection via tiers, redirections | Moyenne |
API1:2023 : Broken Object Level Authorization (BOLA)
Le risque le plus fréquent et souvent le plus impactant. L'API accepte un identifiant d'objet (ID de commande, ID d'utilisateur, UUID de fichier) sans vérifier que le demandeur en est bien le propriétaire ou dispose des droits nécessaires.
Exemple HTTP
GET /api/v1/invoices/1041 HTTP/1.1
Authorization: Bearer <token_compte_B>
HTTP/1.1 200 OK
{"id":1041,"client":"Dupont SAS","amount":12400,"iban":"FR76..."}
L'utilisateur B accède à la facture du client A simplement en décrémentant l'ID.
Ce qu'on teste
Substitution systématique des identifiants dans les paramètres de chemin, de requête et de corps. Test croisé entre deux comptes : compte A tente d'accéder aux objets du compte B avec son propre token. Particulièrement critique sur les plateformes multi-tenant où chaque tenant devrait être totalement isolé.
Remédiation
Vérifier côté serveur, à chaque requête, que l'ID demandé appartient bien à l'utilisateur authentifié. Ne jamais compter sur l'obscurité (UUID vs ID séquentiel) comme seule protection. Implémenter des tests automatisés d'autorisation dans la CI.
API2:2023 : Broken Authentication
Mécanismes d'authentification mal implémentés : tokens prédictibles, absence de protection brute-force sur /login et /reset-password, JWT acceptant l'algorithme none, secrets faibles, absence de rotation, refresh tokens non révocables.
Exemple HTTP : JWT alg:none
# Token original (en-tête décodé)
{"alg":"HS256","typ":"JWT"}
# Token forgé
{"alg":"none","typ":"JWT"}
# Payload modifié : "role":"admin"
# Signature : vide
POST /api/v1/admin/users HTTP/1.1
Authorization: Bearer eyJhbGciOiJub25lIn0.eyJ1c2VyIjoiYXR0YWNrZXIiLCJyb2xlIjoiYWRtaW4ifQ.
HTTP/1.1 200 OK ← serveur accepte le token sans signature
Ce qu'on teste
Force brute sans blocage (10, 100, 1 000 tentatives mesurées), manipulation des JWT (alg:none, alg:RS256→HS256, secret faible cassé par dictionnaire), flux de réinitialisation (OTP court, expiration absente, token de reset non invalidé après usage), expiration des access tokens et des refresh tokens.
Remédiation
Imposer des secrets JWT longs (≥256 bits), rejeter explicitement l'algorithme none, bloquer après N tentatives échouées, expirer les tokens de reset dans les 15 minutes et les invalider après utilisation. Utiliser des bibliothèques à jour plutôt que des implémentations JWT maison.
API3:2023 : Broken Object Property Level Authorization
Fusion de deux entrées de l'édition 2019 : Excessive Data Exposure et Mass Assignment. L'API renvoie plus de champs que nécessaire et/ou accepte en écriture des champs qui ne devraient pas être modifiables.
Exemples HTTP
# Surexposition - GET /api/v1/users/me
HTTP/1.1 200 OK
{
"id": 42,
"email": "user@example.com",
"password_hash": "$2b$12$...", ← ne devrait jamais être exposé
"role": "user",
"internal_score": 84,
"last_ip": "91.134.x.x"
}
# Mass assignment - PUT /api/v1/profile
{"name":"Alice","email":"alice@example.com","role":"admin"}
HTTP/1.1 200 OK ← le rôle a été modifié
Ce qu'on teste
Inspection des réponses pour détecter les champs sensibles (hashes, clés internes, rôles, données financières). Envoi de champs arbitraires dans les requêtes en écriture avec Burp Intruder ou un script de fuzzing JSON.
Remédiation
Définir des schémas de réponse stricts (allowlist de champs) plutôt que de sérialiser l'objet complet. Utiliser des DTOs distincts pour la lecture et l'écriture. Ne jamais binder directement les paramètres de requête sur un modèle de données.
API4:2023 : Unrestricted Resource Consumption
Absence de limites sur les ressources consommées : pas de rate limiting, pagination non obligatoire, tailles de payload non contrôlées, requêtes GraphQL imbriquées sans limite de profondeur ou de coût.
Exemple HTTP : pagination non limitée
GET /api/v1/users?limit=999999&offset=0 HTTP/1.1
Authorization: Bearer <token_valide>
HTTP/1.1 200 OK
[... 2,4 millions d'enregistrements ...] ← exfiltration complète en une requête
Ce qu'on teste
Requêtes répétées (authentifiées et non authentifiées) pour mesurer le seuil de blocage. Envoi de payloads volumineux (Content-Length élevé). Sur GraphQL : requêtes avec aliases multiples et imbrication profonde (query depth attack, batching attack).
Remédiation
Imposer un limit maximum par endpoint (ex. 100 enregistrements), rate limiting par IP et par token, validation de la taille des payloads entrants. Sur GraphQL : activer la limite de profondeur et le coût de requête (query complexity).
API5:2023 : Broken Function Level Authorization
Alors que BOLA porte sur les données (quel objet), BFLA porte sur les actions (quelle opération) : un utilisateur standard peut invoquer des endpoints réservés aux administrateurs parce que le contrôle ne s'effectue que côté interface, pas côté API.
Exemple HTTP
# Le bouton "Supprimer" n'est pas affiché dans l'UI pour un rôle "user"
# Mais l'endpoint existe et répond
DELETE /api/v1/admin/users/99 HTTP/1.1
Authorization: Bearer <token_role_user>
HTTP/1.1 200 OK
{"message":"User deleted"} ← l'opération a réussi
Ce qu'on teste
Cartographie complète des endpoints (Swagger, trafic capturé, fuzzing de préfixes /admin, /internal, /manage, /v2). Rejouer chaque requête sensible avec un token de niveau inférieur. Tester les méthodes HTTP alternatives (DELETE, PUT, PATCH) sur des ressources exposées en lecture seule.
Remédiation
Centraliser les contrôles d'autorisation dans un middleware plutôt que dans chaque handler. Appliquer le principe du moindre privilège par défaut : tout endpoint est privé sauf annotation explicite. Auditer régulièrement la matrice rôle/action.
API6:2023 : Unrestricted Access to Sensitive Business Flows
La requête est authentifiée et techniquement valide, mais elle abuse d'un flux métier : achat en masse lors d'un drop limité, accumulation automatisée de points de fidélité, scraping de catalogue complet, spam de codes de parrainage.
Exemple
Un endpoint POST /api/v1/referrals permet à un utilisateur d'inviter d'autres personnes. Sans limite de cadence, un script génère 10 000 codes de parrainage en quelques minutes pour accumuler des crédits, chaque requête étant individuellement valide.
Ce qu'on teste
Identification des flux à valeur économique (achat, vote, parrainage, cumul de points). Test de cohérence métier : peut-on acheter plus que le stock affiché ? S'auto-référencer ? Émettre plus de coupons qu'autorisé ? Mesure des limites par compte, par IP et par période.
Remédiation
Implémenter des limites d'usage métier spécifiques (pas seulement du rate limiting générique), des vérifications de cohérence côté serveur, et des alertes sur les comportements anormaux (pic soudain d'une action précise par un même compte).
API7:2023 : Server Side Request Forgery (SSRF)
Une entrée utilisateur construit une requête côté serveur vers une destination non validée. Sur AWS, l'endpoint IMDS (169.254.169.254) peut alors être atteint pour récupérer des credentials IAM temporaires. Consultez notre guide détaillé sur SSRF et l'IMDSv2 AWS.
Exemple HTTP : webhook SSRF
POST /api/v1/webhooks HTTP/1.1
Content-Type: application/json
{"url":"http://169.254.169.254/latest/meta-data/iam/security-credentials/ec2-role"}
HTTP/1.1 200 OK
{
"AccessKeyId": "ASIA...",
"SecretAccessKey": "...",
"Token": "...",
"Expiration": "2026-05-03T14:00:00Z"
}
Ce qu'on teste
Tous les paramètres ressemblant à des URLs ou des chemins : webhooks, imports de fichiers distants, previews d'URL, rendus de PDF, conversions de format. Redirections vers localhost, 0.0.0.0, 169.254.169.254, des IPs RFC1918, des services internes (base de données, Redis, Elasticsearch).
Remédiation
Valider les URLs par allowlist de domaines autorisés, résoudre les DNS côté serveur et vérifier que l'IP résolue n'est pas dans un range privé/link-local. Désactiver les redirections HTTP lors des requêtes sortantes. Activer IMDSv2 et restreindre les rôles EC2 au strict nécessaire.
API8:2023 : Security Misconfiguration
Configurations par défaut non durcies : CORS trop permissif, headers de sécurité absents, documentation Swagger accessible en production, schéma GraphQL avec introspection activée, messages d'erreur verbeux exposant la stack technique.
Exemple HTTP : CORS permissif avec credentials
GET /api/v1/profile HTTP/1.1
Origin: https://evil.com
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://evil.com ← origine arbitraire acceptée
Access-Control-Allow-Credentials: true ← cookies inclus
← vol de session possible
Ce qu'on teste
Revue des headers (CORS, HSTS, X-Content-Type-Options, Content-Security-Policy). Accès aux endpoints de documentation (/swagger.json, /openapi.yaml, /api-docs, /graphql avec requête d'introspection). Analyse des messages d'erreur (stack traces, noms de tables, versions de frameworks).
Remédiation
Allowlist explicite des origines CORS autorisées. Désactiver l'introspection GraphQL en production. Retourner des messages d'erreur génériques côté client, logger les détails côté serveur. Appliquer un security header middleware à toute l'API.
API9:2023 : Improper Inventory Management
Des versions anciennes (/v1, /beta, /legacy) ou des endpoints de debug restent accessibles en production avec des contrôles inférieurs à la version courante. Les équipes ne savent souvent pas avec précision quels endpoints sont encore actifs.
Exemple
L'endpoint POST /api/v2/password-reset exige une vérification CAPTCHA et limite les tentatives. L'endpoint POST /api/v1/password-reset, jamais formellement déprécié, n'a ni l'un ni l'autre et répond toujours.
Ce qu'on teste
Fuzzing de préfixes de version (/v0, /v1, /v2, /beta, /internal, /dev, /debug). Comparaison des contrôles entre versions pour chaque endpoint critique. Recherche dans Wayback Machine, GitHub ou les changelogs publics d'anciens endpoints.
Remédiation
Tenir un inventaire vivant de tous les endpoints actifs (généré automatiquement depuis le code, pas maintenu manuellement). Déprécier formellement les anciennes versions avec une date de fin et les supprimer au lieu de les désactiver en silencieux. Intégrer des tests de régression couvrant les anciennes routes.
API10:2023 : Unsafe Consumption of APIs
L'application consomme des API tierces (partenaires, fournisseurs de données, webhooks entrants) en leur faisant implicitement confiance. Une API tierce compromise ou malveillante peut injecter des données traitées sans validation, conduisant à des injections ou des redirections non contrôlées.
Exemple
Un service de paiement tiers renvoie un champ "redirect_url" après confirmation. L'application redirige l'utilisateur vers cette URL sans vérification. Un attaquant qui compromet l'API tierce peut injecter une URL de phishing ciblée qui s'affiche sous le domaine de confiance.
Ce qu'on teste
Identification des dépendances vers des API externes. Vérification que les réponses tierces sont validées avant usage : désérialisation (protobuf, XML), redirections, contenu HTML réinjecté dans une vue, données utilisées dans des requêtes SQL ou des commandes shell.
Remédiation
Traiter toute réponse d'API tierce comme une entrée non fiable : valider le schéma, encoder les sorties, ne pas suivre aveuglément les redirections. Surveiller les changements de comportement des API tierces (monitoring, alertes sur les anomalies de réponse).
Ce qui a changé entre 2019 et 2023
| 2019 | 2023 | Évolution |
|---|---|---|
| Broken Object Level Authorization | API1 : BOLA | Inchangé, toujours #1 |
| Broken User Authentication | API2 : Broken Authentication | Élargi (pas seulement les users) |
| Excessive Data Exposure | API3 : Broken Object Property Level Authorization | Fusionné avec Mass Assignment |
| Mass Assignment | ||
| Lack of Resources & Rate Limiting | API4 : Unrestricted Resource Consumption | Élargi aux coûts cloud |
| Broken Function Level Authorization | API5 : BFLA | Inchangé |
| (aucun) | API6 : Unrestricted Access to Sensitive Business Flows | Nouveau en 2023 |
| Security Misconfiguration | API8 : Security Misconfiguration | Repositionné |
| Injection | Absorbé dans API8 et API10 | Supprimé comme entrée distincte |
| Improper Assets Management | API9 : Improper Inventory Management | Renommé |
| (aucun) | API7 : SSRF | Nouveau en 2023 |
| (aucun) | API10 : Unsafe Consumption of APIs | Nouveau en 2023 |
Les trois nouveautés (SSRF, flux métier, consommation non sécurisée) reflètent la généralisation des architectures cloud et des intégrations tierces depuis 2019.
Outils pour tester l'OWASP API Security Top 10
- Burp Suite : proxy incontournable pour intercepter, rejouer et modifier les requêtes API. L'extension Autorize automatise les tests BOLA/BFLA entre comptes.
- ffuf / feroxbuster : fuzzing d'endpoints et de versions (
/v1,/admin,/internal). Rapide, configurable avec des wordlists OWASP. - jwt_tool : manipulation et exploitation de JWT : alg:none, brute-force de secret, confusion RS256/HS256.
- Postman / Insomnia : exploration et documentation des API, utiles en phase de cartographie pour reconstruire la collection complète des endpoints.
- GraphQL Voyager + InQL : visualisation du schéma GraphQL et génération automatique de cas de test pour l'introspection et les requêtes imbriquées.
- crAPI (OWASP) : environnement de lab délibérément vulnérable, idéal pour pratiquer chaque entrée de la liste dans un contexte réaliste.
Ce que cette liste change par rapport au Top 10 web
Les risques API ne sont pas une simple déclinaison du Top 10 web. Plusieurs différences structurelles importent :
- Pas de session navigateur : l'authentification repose sur des tokens (JWT, OAuth, clés API) dont la validation est souvent incomplète côté serveur.
- Autorisation granulaire : BOLA et BFLA n'ont pas d'équivalent direct dans le Top 10 web, ils sont propres à la logique d'accès par objet et par action des API.
- Surface plus large : une API REST peut exposer des centaines d'endpoints souvent générés automatiquement, sans revue de sécurité systématique.
- Données plus exposées : les réponses JSON brutes tendent à renvoyer plus de champs que nécessaire, là où une vue HTML aurait simplement omis l'affichage.
Lors d'un pentest web méthodique, la phase de cartographie des API doit être traitée comme un périmètre à part entière, avec ses propres cas de test. Pour les plateformes SaaS exposant une API publique, consultez notre page dédiée au pentest SaaS.
Questions fréquentes
Quelle est la différence entre l'OWASP Top 10 web et l'OWASP API Security Top 10 ?
L'OWASP Top 10 web couvre les vulnérabilités des applications web classiques (HTML, sessions navigateur). L'OWASP API Security Top 10 cible les interfaces programmatiques (REST, GraphQL, gRPC) où les vecteurs d'attaque diffèrent : pas de session navigateur, logique d'autorisation par objet, exposition de données via surcharge de réponse.
BOLA et IDOR : quelle différence ?
IDOR (Insecure Direct Object Reference) est le nom historique du problème. BOLA (Broken Object Level Authorization) est la terminologie OWASP API, plus précise : elle insiste sur le fait que c'est le contrôle d'autorisation au niveau de l'objet (et non seulement la référence directe) qui est absent ou insuffisant.
Comment tester l'OWASP API Security Top 10 lors d'un pentest ?
Un pentest API suit une méthodologie structurée : cartographie des endpoints (Swagger, introspection GraphQL, trafic capturé), test des contrôles d'autorisation horizontale et verticale, fuzzing des paramètres, analyse des réponses pour détecter les surcharges de données, et test des flux métier sensibles. Notre offre de pentest web intègre systématiquement cette couverture API.