Guide de test de sécurité des API
Recommandés
Une API sûre n’est pas celle qui « passe les tests », c’est celle qui résiste aux idées tordues. Ce guide vous donne une trame de test actionnable, pensée pour les REST/JSON, GraphQL et gRPC, avec un focus sur les faiblesses réelles (authz, BOLA, rate limit, injections, logique métier) et des exemples concrets. Aucune dépendance à des liens externes, juste de la pratique.
1) Préparer le terrain (avant de taper une seule requête)
1.1 Inventaire & contrat
- Recenser toutes les surfaces d’attaque : REST
/v1/*, GraphQL/graphql, gRPC services, webhooks, fichiers (upload/download), temps réel (SSE/WebSocket), admin/ops. - Comparer l’implémentation au contrat (OpenAPI/Protobuf/SDL GraphQL). Identifier écarts (endpoints non documentés, champs exposés en plus, types permissifs).
- Distinguer API publiques, partenaires, internes : les exigences diffèrent (authent, quotas, données).
1.2 Comptes & jeux de données
- Créer 3 profils minimum : utilisateur sans privilèges, utilisateur standard, administrateur (ou rôles métiers).
- Jeu de données semi-réaliste : identifiants distincts, objets appartenant à différents propriétaires, cas limites (zéros, montants négatifs, dates anciennes, très futures).
1.3 Environnement & observabilité
- Activer logs corrélables (trace-id), masquage des secrets, niveau d’erreur non verbeux en prod.
- Prévoir monitoring du 401/403/429/5xx pendant les tests, et quotas isolés par environnement.
2) Méthode : ordre de frappe recommandé
- Authentification → 2) Autorisation (objets & actions) → 3) Entrées & injections → 4) Disponibilité (limites & quotas) → 5) Confidentialité (données) → 6) Visibilité (logs, erreurs) → 7) Chaîne d’approvisionnement.
3) Tests essentiels par thématique
3.1 Authentification (qui suis-je ?)
- JWT/OAuth : vérifier
iss/aud/sub/exp/nbf/iat, tolérance d’horloge, rotation des clés, refus dealg=none. - Enforcer PKCE pour clients publics. Scopes granuleux, pas de « scope fourre-tout ».
- mTLS si nécessaire (B2B/partenaires sensibles).
- Rejet des tokens expirés/révoqués, replay bloqué (nonce/timestamp).
Exemples
# Token expiré
curl -H "Authorization: Bearer <jwt_expiré>" https://api.local/v1/me -i
# Changer le 'aud' et signer avec une autre clé doit échouer
# Vérifier 401/403 et message non verbeux.
3.2 Autorisation (ai-je le droit ?)
Cœur des failles API (BOLA/BFLA/IDOR) : accès à un objet qui ne m’appartient pas ou action non permise.
Cas à forcer
- Changer un
:iddans/users/{id}/orders. - Soumettre un objet avec ownerId d’autrui.
- Essayer DELETE/PUT sur ressource d’un autre.
- GraphQL : requêtes avec alias/batching pour traverser des frontières d’autorisations.
Exemples
# IDOR / BOLA
curl -H "Authorization: Bearer <userA>" https://api.local/v1/users/USER_B/orders -i
# Mass assignment : injection d’un champ sensible
curl -X PATCH https://api.local/v1/users/me \
-H "Authorization: Bearer <user>" -H "Content-Type: application/json" \
-d '{"role":"admin","email":"me@ex.com"}'
Attendus
- 403 au lieu de 404 « masquant » quand l’objet existe mais n’est pas autorisé (selon politique).
- Les champs sensibles ignorés côté serveur (whitelist) ; pas d’écriture silencieuse.
3.3 Validation d’entrée & injections
- Types : nombres, bool, dates → refuser chaînes ambiguës.
- Tailles & bornes : longueur max, valeur min/max, ensembles autorisés.
- Injections : SQL/NoSQL, Commande, LDAP, Template.
- Objets imbriqués : JSON profondément nesté, arrays gigantesques, null/NaN/Infinity.
Corpus rapide de fuzz (échantillon)
["", " ", "\n", "\u0000", "\"'<>", "${{7*7}}", "../etc/passwd",
0, -1, 9999999999, 0.0, 1e309, null, [], {}, ["a","a","a"...x1000] ]
GraphQL
- Introspection désactivée en prod (sauf besoin).
- Limiter profondeur et complexité (coûts par champ).
- Empêcher alias batching d’autorisations.
3.4 Limites, quotas, anti-abus
- Rate limiting par IP/clé/compte, 429 cohérent.
- Burst vs soutenu : tester les deux.
- Pagination stricte (taille max), interdire
?limit=100000. - Téléversement : taille max, MIME sniffing, lecture de magic bytes.
- Compression : refuser notes de type « zip bomb » si non utile.
Exemples
# Abus de pagination
curl "https://api.local/v1/items?limit=100000&offset=0" -i
# Rafale 50 requêtes/s (outil draineur ou boucle shell) → attendre 429 avec backoff.
3.5 Confidentialité & vie privée
- Sortie d’API : pas d’attributs non nécessaires (PII minimisée).
- Masquage dans logs/traces (tokens, IBAN, cartes).
- Cache-Control correct pour données sensibles.
- ETag/Last-Modified : pas de fuite de contenu privé via caches partagés.
3.6 Erreurs & messages
- Aucune stack trace en prod, pas d’info sur la base/driver.
- Codes HTTP cohérents (400/401/403/404/409/422/429/5xx).
- Corps d’erreur stable : code, message, corrélation (trace-id).
3.7 Webhooks
- Signature (HMAC) sur le corps, horodatage & replay window courte.
- TLS strict, éventuellement allowlist d’IP.
- Refuser content-type non attendu, vérifier digest.
3.8 gRPC
- Auth au niveau service et méthode.
- Limites sur tailles de messages, refuse streams infinis.
- Erreurs mappées proprement vers statuts (UNAUTHENTICATED, PERMISSION_DENIED…).
4) Non-fonctionnel : sécurité qui tient la charge
- Déni de service logique : requêtes coûteuses (tri, aggrégations, expansions) → time-outs et coûts limités.
- Concurrence : tests de race condition (deux PATCH simultanés) → verrouillage optimiste (ETag/If-Match) ou versionnage.
- Temps de réponse sous contrainte (budget SLO).
- Dégradation contrôlée : quotas par client, backpressure, file d’attente.
5) Modèle de plan de test (prêt à coller)
5.1 Portée
- Surfaces : REST
/v1/*, GraphQL/graphql, Webhooks/hook/*, Upload/files. - Rôles : guest, user, admin.
- Données : jeu anonymisé + comptes dédiés.
5.2 Critères de réussite (extraits)
- 100 % des endpoints protégés (pas d’endpoint orphelin).
- Authz objet : 0 passage BOLA/IDOR.
- Limites : 429 déclenché aux seuils définis, pas d’épuisement global.
- Erreurs : pas de stack trace, messages sobres.
- Webhooks : signature vérifiée, anti-replay OK.
5.3 Cas de test minimaux
- Auth : expiré, futur, mauvais
aud, rafraîchissement, rotation clé. - Authz : GET/PUT/DELETE d’un objet tiers ; champ sensible injecté.
- Entrée : corpus fuzz ci-dessus sur tous les champs
user_input. - Quota : rafale 10× le budget, window glissante.
- Upload : double extension
file.jpg.exe, MIME falsifié, magic bytes.
5.4 Gabarit de rapport
- Titre :
BOLA sur /orders/{id} - Gravité : Critique
- Contexte : user A lit l’ordre de user B.
- Étapes : 1) login user A ; 2) GET /orders/ID_B ; 3) 200 avec corps.
- Impact : violation confidentialité.
- Remède : vérifier ownership côté serveur (policy ABAC/RBAC + filtre repo).
- Preuve : requête & réponse minimales (masquées).
6) Spécificités par techno
REST
- Content-Type strict (
application/json) ; rejetertext/plain. - Accept négocié ; réponses cohérentes sur erreurs (RFC 7807-like).
- Idempotence :
PUT/DELETEré-essayables ; replay maîtrisé.
GraphQL
- Limites de profondeur/complexité ; introspection restreinte.
- Autorisations par champ (field-level) si données hétérogènes.
- Batching/alias : empêcher l’agrégation qui contourne l’authz.
gRPC
- Intercepteurs d’auth systématiques ; journaux sans secrets.
- Messages bornés ; circuit breakers pour streams.
7) Données & crypto
- TLS à jour, désactiver suites faibles.
- At-rest : chiffrage des secrets, rotation régulière.
- Signatures stables (HMAC/clé privée) pour webhooks & requêtes critiques.
- Clés : pas dans le code, pas dans les réponses, pas dans les logs.
8) Automatiser intelligemment
- Tests de contrat (schéma ↔ implémentation) à chaque build.
- Tests d’autorisations générés par jeux d’objets (propriétaire / non-propriétaire).
- Fuzz léger sur pipeline (mutations simples), fuzz profond en nightly.
- Canaris en pré-prod : quotas, erreurs, latences sous charge.
Couverture minimale utile
- 100 % des endpoints touchés au moins 1 fois par rôle.
- 100 % des changements d’état testés (POST/PATCH/DELETE).
- 100 % des chemins admin ou sensibles.
9) Checklists prêtes à cocher
Auth
- Tokens expirés/rejoués rejetés
iss/audvérifiés- Rotation clés/JWKS testée
- Scopes appliqués par endpoint
Authz
- Pas d’accès cross-tenant
- BOLA/IDOR bloqués
- Mass assignment neutralisé
Entrée
- Types, tailles, bornes strictes
- Encodages & caractères de contrôle refusés
- JSON profonds/énormes refusés proprement
Abus
- 429 sur rafales & soutenu
- Pagination max respectée
- Uploads contrôlés (taille/MIME/magic bytes)
Confidentialité & erreurs
- Pas de PII inutile
- Logs sans secrets
- Messages d’erreur sobres, sans stack
Webhooks
- Signature/HMAC validée
- Anti-replay (timestamp/nonce)
- TLS strict
10) Kit « 2 heures avant mise en prod »
- Balayer tous les endpoints avec un token utilisateur et un token d’un autre tenant → vérifier 403.
- Changer les IDs et retester GET/PUT/DELETE.
- Corpus fuzz sur 3 champs critiques.
- Rafale sur deux endpoints coûteux → 429 attendu.
- Upload 3 fichiers suspects (gros, double extension, MIME faux).
- Webhooks : rejouer une notification avec vieux timestamp → doit échouer.
- Logs d’une 5xx : pas de secrets, trace-id présent.
Le meilleur testeur d’API se comporte en mauvais client: il bidouille les IDs, envoie des champs inattendus, abuse des limites et observe ce que l’API révèle. Avec ce guide, vous avez une base opérationnelle pour casser avant que d’autres ne cassent—et pour reconstruire, proprement, avec des garde-fous mesurables.






