La défense des API par un praticien : autorisation par objet, contrat OpenAPI audité en CI, JWT verrouillé, mTLS entre services.
Pourquoi ce livre
Une API financière passe un ordre en deux appels : préparer, puis exécuter. Or le second appel croit sur parole le compte source fourni par le client. Un attaquant le remplace par un compte vide, et l'API ne revérifie rien (leçon 63).
Colin Domoney raconte ce genre de faille dans Defending APIs. Sa thèse, telle que je la lis : une API se défend avant la production et après. Avant, c'est le shift-left : contrat, analyse du code, tests. Après, c'est le shield-right : passerelle d'entrée, trafic entre services.
De mon côté, je travaille en fintech et en crypto, en Go et en PHP avec Symfony. Qu'apporte ce cours à qui défend déjà des API sensibles ? Je l'ai lu sur ExpertEdge, bases, brèches et outils de reconnaissance survolés. Mes comparaisons sont signalées par « Ma lecture ».
Six idées en deux familles : 1 à 4 avant la production, 5 et 6 en ligne.
Les idées qui restent
1Le test A-B prouve qu'un utilisateur ne lit pas l'objet d'un autre
Première famille : le code. Le livre suit le Top 10 des failles d'API de l'OWASP (Open Worldwide Application Security Project). En tête vient le BOLA (Broken Object Level Authorization) : l'utilisateur connecté change le numéro dans l'URL et lit le reçu d'un autre client.
Le remède : autoriser « chaque accès à un objet, sans exception » (leçon 19). Le BOLA a un cousin, le BFLA (Broken Function Level Authorization) : être connecté n'ouvre pas les fonctions d'administration.
La preuve : le test A-B. L'utilisateur A crée une ressource, l'utilisateur B tente d'y accéder. « Si vous y arrivez, vous avez un problème d'autorisation » (leçon 49). L'auteur conseille d'écrire ces tests soi-même, mais n'en montre aucun (leçon 63).
Après l'audit d'un service Go, je ne garde en test permanent que les attaques qu'un changement de bonne foi pourrait réintroduire. Une route qui oublie le propriétaire en serait une.
2Trois objets distincts ferment la porte au mass assignment
L'autorisation dit qui touche à un objet, pas quels champs l'API accepte. Le mass assignment (affectation en masse) naît d'un raccourci : le framework copie tous les champs reçus vers la base. L'attaquant ajoute "is_admin": true, et l'API l'enregistre.
La parade du livre tient en trois objets (leçon 65) :
- L'objet d'entrée : ce que le client peut envoyer.
- L'objet de base : ce qui est stocké, mot de passe haché compris.
- L'objet de sortie : ce que le client peut lire.
Pour l'auteur, la plupart des failles de données viennent d'un passage direct entre objets « sans considérer la sensibilité des données » (leçon 65). Ma traduction en Go, pas celle du livre (en Python) :
type UserIn struct { // ce que le client peut envoyer
Email string `json:"email"`
Password string `json:"password"`
}
type UserInDB struct { // ce qui est stocké
Email string
PasswordHash string
IsAdmin bool
}
type UserOut struct { // ce que le client peut lire
Email string `json:"email"`
}
func createUser(w http.ResponseWriter, r *http.Request) {
var in UserIn
if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
http.Error(w, "requête invalide", http.StatusBadRequest)
return
}
// un "is_admin" envoyé n'a nulle part où aller : UserIn n'a pas ce champ
db := UserInDB{Email: in.Email, PasswordHash: hashPassword(in.Password)}
save(db)
json.NewEncoder(w).Encode(UserOut{Email: db.Email}) // ni hash ni rôle
}
// hashPassword (argon2id ou bcrypt) et save : non montrés
Le décodage ne remplit que UserIn. Le passage vers UserInDB est écrit à la main, hachage compris, comme dans le livre. Rien ne sort sans place dans UserOut.
3Le contrat OpenAPI devient une règle que l'intégration continue fait respecter
Ces objets se décrivent aussi dans un contrat OpenAPI, le format standard des routes, champs, types et limites d'une API. Pour le livre, « la définition est le contrat, tout ce qui n'est pas dans le contrat est invalide » (leçon 55).
Un audit repère ce qui reste ouvert, comme un entier sans maximum. Le contrat exige l'authentification partout, puis la relâche route par route : une route oubliée reste fermée (leçon 56).
Cet audit tourne dans l'intégration continue (CI), la chaîne qui teste chaque modification avant la fusion, et un défaut grave peut casser le build. L'outil doit rester rapide, « idéalement moins d'une minute » (leçon 58).
4Un JWT se vérifie avec l'algorithme du serveur, jamais avec celui du jeton
Un piège échappe à l'audit du contrat : le JWT (JSON Web Token), un jeton signé qui porte l'identité de l'utilisateur. En CI, Semgrep, un outil qui cherche des motifs dans le code, repère un jeton décodé sans vérifier sa signature (leçon 58). Or l'en-tête du JWT annonce l'algorithme, et c'est le client qui l'écrit.
L'attaquant peut y écrire none, « pas de signature », ou signer en symétrique avec la clé publique du serveur (leçons 47 et 48). Une bibliothèque qui suit l'en-tête accepte alors son faux jeton.
La parade : « soyez explicite sur l'algorithme et la clé utilisés, et ignorez les valeurs fournies dans l'en-tête du JWT » (leçon 60).
5À la passerelle, le client ne voit jamais le vrai jeton
Seconde famille : l'API en ligne. La passerelle d'API (API gateway) reçoit les appels extérieurs et les route vers les services. Or un JWT est signé, pas chiffré : son destinataire le lit.
Un JWT colle trois parties : en-tête, contenu, signature. Le livre décrit deux façons de cacher le contenu (leçon 86) :
- Le jeton opaque (phantom token) : le client ne reçoit qu'une référence, échangée à chaque appel contre le vrai JWT, au prix de calcul et d'« un point de défaillance unique et central ».
- Le split token (jeton coupé en deux) : le client ne reçoit que la signature, et la passerelle retrouve le jeton entier en cache (moins de goulot, selon l'auteur).
Aucun code, et rien sur la révocation d'un jeton déjà émis (leçon 86).
6Entre deux services, le mTLS va de soi
La passerelle protège en général le trafic nord-sud, pas le trafic ouest-est, celui qui circule entre les services (leçon 80). Pour celui-là, le livre pose le mTLS (mutual TLS). TLS chiffre HTTPS. En mode mutuel, client et serveur présentent chacun un certificat et vérifient celui de l'autre.
Sa conclusion : le mTLS « doit être considéré comme acquis dans tout déploiement de microservices » (leçon 84). Rien sur la rotation, la révocation ou le lien jeton-certificat.
Mon article sur la révocation en mTLS couvre l'un de ces manques : revérifier le certificat à chaque requête, même sur une connexion ouverte. Un autre lie la session au numéro de série du certificat client : un cookie volé est refusé ailleurs, sauf vol de la clé privée. C'est voisin du lien jeton-certificat.
Mon avis, honnêtement
Mon verdict, 6,4 sur 10 : un bon récapitulatif, peu de neuf pour un développeur rodé. Qu'apporte ce cours à qui défend déjà des API sensibles ? Six gestes nets, et beaucoup de pages à survoler. D'où une fiche courte : un bon tiers du cours parle d'attaque, la fin de programme d'entreprise.
Sa force : des gestes nommés, chacun réduit à une règle testable.
Ses faiblesses, avec leur coût pour vous :
- Le code d'exemple est à ne pas copier. Mot de passe haché en md5, algorithme périmé, mauvais code de refus, contrôle d'accès incomplet (leçons 63 à 65, détails plus bas). Coût : prenez les principes, jamais les extraits.
- Pas de défense en Go ni en PHP, pas de finance réglementée. Aucun profil de sécurité bancaire, Open Banking cité une fois en passant. Coût : tout est à traduire et à compléter ailleurs.
- L'auteur vend un peu ce qu'il recommande. Domoney a été évangéliste chez 42Crunch, éditeur d'outils de sécurité, dont son modèle de maturité porte le nom (leçon 90). Dans le domaine Protection, le niveau abouti exige un pare-feu d'API : un filtre qui refuse ce que le contrat n'autorise pas, comme celui de 42Crunch démontré au cours (leçon 80). Coût : chaque outil cité est une publicité possible.
- Journaux et limite de débit restent minces. Le cours journalise à la passerelle (leçons 79 et 80) sans dire quoi garder ni combien de temps. La limite d'appels se fait « généralement » par adresse IP (leçon 67). Le limiteur de ma passerelle personnelle en Go aussi, je l'avoue. Coût : à concevoir seul.
Mon conseil : lisez les leçons 19, 49, 55 à 66, 84 et 86, et survolez le reste.
Odilon
Toujours valable en 2026 ?
Les principes, oui. Trois points ont vieilli ou manquaient déjà :
- Les numéros OWASP : le cours mélange 2019 et une version provisoire de 2023 (SSRF en API6, mauvaise configuration en API7). Dans la liste finale, SSRF, le serveur forcé d'appeler l'adresse de l'attaquant, passe en API7. La mauvaise configuration passe en API8, l'abus d'un parcours métier légitime en API6.
- La finance : le cours ne cite ni FAPI (Financial-grade API, le profil OAuth des API financières), ni DPoP, qui lie le jeton à une clé du client. Ni la RFC 8705, qui le lie au certificat mTLS, ni PSD2, la directive européenne des paiements.
- Le code : md5 pour le mot de passe (leçon 65), 401 (« qui êtes-vous ? ») au lieu de 403 (« je sais, et c'est non ») pour un droit manquant (leçon 63). L'exemple Casbin, une bibliothèque d'autorisation, recrée son moteur à chaque requête (un avantage, selon l'auteur). Il contrôle l'URL, pas le propriétaire : à mon avis, il ne traite pas le BOLA (leçon 64).
Pour qui ?
Lisez-le si
- Vous voulez des gestes nommés et testables
- Vous préparez une revue de sécurité (listes de contrôle, leçon 90)
- Vous écrivez votre premier contrat OpenAPI
- Vous montez un programme de sécurité d'API
Passez si
- Vous cherchez du code Go ou PHP
- Vous travaillez sous FAPI ou PSD2, que le livre ignore
- Vous voulez d'abord l'attaque : lisez Web Application Security d'Andrew Hoffman (la fiche, 7,8/10)
Fiche fondée sur la version cours ExpertEdge, 104 leçons annoncées quiz compris. « Ma lecture » et le code Go sont de moi.
Source : version cours ExpertEdge (1re édition Packt 2024), leçons 17 à 23 et 44 à 92 lues en détail.
Commentaires (0)