1. À propos de la sécurité des API
La sécurité des API, ou API Security, désigne l'ensemble des techniques, règles et bonnes pratiques destinées à protéger les interfaces de programmation applicative contre les accès non autorisés, les abus, les fuites de données et différentes formes d'attaques.
Une API, pour Application Programming Interface, permet à plusieurs applications ou composants logiciels de communiquer et d'échanger des données selon des règles définies.
Les API sont aujourd'hui utilisées dans les applications Web, les applications mobiles, les architectures microservices, les services cloud, les objets connectés et de nombreuses plateformes utilisant l'intelligence artificielle.
Exemple d'utilisation d'une API
Une application de commerce électronique peut utiliser une API pour demander au serveur les informations concernant un produit. Une requête peut conceptuellement demander la ressource suivante :
GET /api/produits/125
Le serveur peut répondre avec les informations autorisées concernant le produit numéro 125.
Une API insuffisamment protégée peut cependant permettre à un utilisateur non autorisé d'accéder à des données confidentielles ou d'effectuer des opérations qui ne lui sont pas destinées.
Objectifs de la sécurité des API
- protéger la confidentialité des données ;
- garantir leur intégrité ;
- maintenir la disponibilité du service ;
- authentifier correctement les utilisateurs et applications ;
- contrôler les autorisations ;
- empêcher les accès non autorisés aux ressources ;
- limiter les abus et requêtes excessives ;
- valider les données reçues ;
- surveiller les activités suspectes ;
- protéger les secrets et clés d'API.
Pourquoi les API sont-elles des cibles importantes ?
Les API constituent souvent une interface directe avec les données et les fonctions métier d'une application. Une vulnérabilité peut donc permettre d'accéder à des informations sensibles ou d'effectuer certaines opérations sans autorisation appropriée.
La sécurité doit par conséquent être intégrée dès la conception de l'API et non ajoutée uniquement après son déploiement.
2. Principales menaces contre les API
Une API peut être confrontée à différentes vulnérabilités. Certaines sont liées à l'authentification, d'autres à l'autorisation, à la validation des entrées ou encore à une mauvaise configuration du serveur.
Contrôle d'accès insuffisant
Un problème particulièrement important apparaît lorsqu'une API vérifie qu'un utilisateur est connecté, mais ne vérifie pas correctement s'il possède le droit d'accéder à la ressource demandée.
Supposons qu'un utilisateur possède le compte numéro 125 et consulte une ressource associée à son compte. Si la modification d'un identifiant dans la requête lui permet d'obtenir les informations du compte 126 sans autorisation, le contrôle d'accès est insuffisant.
Authentification insuffisante
Une mauvaise gestion des mots de passe, des jetons, des sessions ou des mécanismes de récupération de compte peut permettre à un attaquant d'usurper l'identité d'un utilisateur.
Exposition excessive des données
Une API doit retourner uniquement les informations nécessaires. Envoyer un objet complet au client puis compter sur l'interface graphique pour masquer les champs confidentiels est une mauvaise pratique.
Le serveur doit effectuer lui-même la sélection des informations autorisées.
Injection
Une injection peut apparaître lorsque les données fournies par un utilisateur sont intégrées de manière non sécurisée dans une requête SQL, une commande ou un autre interpréteur.
L'utilisation de requêtes paramétrées, de bibliothèques adaptées et d'une validation correcte des données permet de réduire fortement ce risque.
Mauvaise configuration
Une mauvaise configuration de sécurité peut exposer des informations ou des services qui ne devraient pas être accessibles.
Les problèmes peuvent notamment concerner :
- les messages d'erreur trop détaillés ;
- des services inutiles laissés actifs ;
- des permissions excessives ;
- des interfaces d'administration exposées ;
- des paramètres par défaut non sécurisés ;
- une configuration CORS trop permissive.
Absence de limitation des requêtes
Une API qui accepte un nombre illimité de requêtes peut être exposée aux abus, à l'épuisement de ressources et à certaines attaques automatisées.
La mise en place d'un rate limiting permet de limiter le nombre de requêtes autorisées pendant une période donnée.
3. Authentification et gestion des accès
L'authentification permet de déterminer l'identité d'un utilisateur ou d'une application, tandis que l'autorisation détermine les actions que cette identité est autorisée à effectuer.
Authentification et autorisation
| Mécanisme | Question | Exemple |
|---|---|---|
| Authentification | Qui êtes-vous ? | Vérifier l'identité d'un utilisateur |
| Autorisation | Que pouvez-vous faire ? | Vérifier le droit d'accéder à une ressource |
Une API sécurisée doit généralement effectuer ces deux contrôles lorsque la ressource demandée l'exige.
Clé API
Une clé API est une valeur permettant notamment d'identifier ou d'authentifier une application cliente dans certains systèmes.
Une clé API doit être considérée comme un secret lorsqu'elle donne accès à des ressources protégées. Elle ne doit pas être publiée dans un dépôt Git public, intégrée directement dans un code source destiné à être distribué ou affichée dans une page Web accessible publiquement.
Jetons d'accès
De nombreuses API utilisent des jetons d'accès. Après une authentification réussie, le client reçoit un jeton qu'il transmet ensuite au serveur pour les requêtes nécessitant une authentification.
JWT
Le JWT, ou JSON Web Token, est un format de jeton largement utilisé. Un JWT peut contenir différentes informations appelées claims.
Il est important de comprendre qu'un JWT signé n'est pas automatiquement chiffré. Son contenu peut souvent être décodé par le client. Il ne faut donc pas y placer des informations confidentielles en supposant qu'elles sont cachées.
OAuth 2.0 et OpenID Connect
OAuth 2.0 est un cadre d'autorisation permettant notamment de déléguer certains accès sans transmettre directement le mot de passe de l'utilisateur à chaque application cliente.
OpenID Connect ajoute une couche d'identité au-dessus d'OAuth 2.0 et est fréquemment utilisé pour l'authentification des utilisateurs.
Principe du moindre privilège
Le principe du moindre privilège consiste à attribuer uniquement les permissions nécessaires à l'accomplissement d'une tâche.
Un utilisateur chargé uniquement de consulter les produits d'un catalogue ne devrait par exemple pas recevoir automatiquement l'autorisation de supprimer ou modifier ces produits.
Vérifier les autorisations côté serveur
Le programme Python suivant illustre le principe d'un contrôle d'autorisation. L'accès est accordé uniquement lorsque l'utilisateur authentifié correspond au propriétaire de la ressource demandée.
1 2 3 4 5 6 | utilisateur_connecte = 125 proprietaire_ressource = 125 if utilisateur_connecte == proprietaire_ressource: print("Accès autorisé") else: print("Accès refusé") |
Sortie :
1 | Accès autorisé |
Dans une véritable API, ce contrôle doit être effectué côté serveur pour chaque ressource nécessitant une autorisation. Une vérification réalisée uniquement dans l'interface cliente ne constitue pas une protection suffisante.
4. Validation des données et protection des échanges
Une API ne doit jamais considérer automatiquement les données envoyées par le client comme fiables. Toutes les entrées pertinentes doivent être validées côté serveur.
Validation des entrées
La validation peut notamment vérifier :
- le type de la donnée ;
- sa longueur ;
- les valeurs minimales et maximales ;
- les champs obligatoires ;
- le format attendu ;
- les valeurs autorisées.
Valider une quantité
Le programme suivant vérifie qu'une quantité reçue respecte les règles définies par l'application. Seuls les nombres entiers compris entre 1 et 100 sont acceptés.
1 2 3 4 5 | quantite = 25 if isinstance(quantite, int) and 1 <= quantite <= 100: print("Quantité valide") else: print("Quantité invalide") |
Sortie :
1 | Quantité valide |
Dans une API réelle, une valeur invalide doit provoquer une réponse appropriée plutôt que d'être utilisée directement dans le traitement métier.
Utiliser des requêtes SQL paramétrées
Lorsqu'une API communique avec une base de données SQL, les valeurs fournies par les utilisateurs ne doivent pas être concaténées directement dans les requêtes. Le programme suivant utilise une requête paramétrée avec SQLite.
1 2 3 4 5 6 7 8 9 10 11 | import sqlite3 connexion = sqlite3.connect("boutique.db") curseur = connexion.cursor() identifiant = 125 curseur.execute( "SELECT nom, prix FROM produits WHERE id = ?", (identifiant,) ) produit = curseur.fetchone() print(produit) connexion.close() |
Sortie :
1 | ('Clavier', 250.0) |
La valeur de l'identifiant est transmise séparément de la requête SQL. Cette méthode est préférable à la construction d'une requête en concaténant directement une valeur fournie par l'utilisateur.
Utiliser HTTPS
Les API accessibles sur Internet doivent utiliser HTTPS afin de protéger les communications grâce à TLS. Cela réduit notamment les risques d'interception et de modification des données pendant leur transport.
Les mots de passe, jetons d'accès, clés et autres informations confidentielles ne doivent pas être transmis en clair sur un réseau non sécurisé.
Protéger les secrets
Les clés API, mots de passe de base de données et autres secrets ne doivent pas être directement inscrits dans le code source lorsque cela peut être évité.
Selon l'environnement, ils peuvent être conservés dans des variables d'environnement ou dans un gestionnaire de secrets adapté.
Limiter les données retournées
Une API doit également contrôler les données présentes dans ses réponses. Un endpoint destiné à afficher un profil public ne doit pas retourner inutilement des informations internes ou confidentielles.
5. Rate limiting, journalisation et surveillance
La sécurité d'une API ne repose pas uniquement sur l'authentification. Il faut également contrôler son utilisation et disposer de mécanismes permettant de détecter les comportements anormaux.
Rate limiting
Le rate limiting consiste à limiter le nombre de requêtes qu'un client peut effectuer pendant une période donnée.
Une politique peut par exemple autoriser un nombre déterminé de requêtes par minute selon le type d'utilisateur, le service ou l'endpoint concerné.
Cette mesure peut contribuer à limiter :
- les abus automatisés ;
- certaines tentatives massives d'authentification ;
- le scraping excessif ;
- l'épuisement de certaines ressources ;
- certaines formes de déni de service applicatif.
Simuler une limitation de requêtes
Le programme Python suivant présente un exemple pédagogique très simplifié. Il vérifie si le nombre de requêtes effectuées reste inférieur ou égal à la limite autorisée.
1 2 3 4 5 6 | limite = 100 nombre_requetes = 72 if nombre_requetes <= limite: print("Requête autorisée") else: print("Limite dépassée") |
Sortie :
1 | Requête autorisée |
Dans une véritable API distribuée, la limitation nécessite généralement un mécanisme capable de suivre les requêtes de manière fiable entre plusieurs processus ou serveurs.
Journalisation
La journalisation permet d'enregistrer les événements importants liés à l'utilisation de l'API.
Les journaux peuvent contenir, selon les besoins et les contraintes de confidentialité :
- la date et l'heure ;
- l'endpoint demandé ;
- le code de réponse HTTP ;
- l'identifiant technique de l'utilisateur lorsque cela est approprié ;
- les échecs d'authentification ;
- les erreurs applicatives ;
- certaines opérations sensibles.
Ne pas enregistrer les secrets
Les journaux ne doivent pas contenir inutilement les mots de passe, clés API, jetons d'accès complets ou autres secrets. Une journalisation excessive peut elle-même provoquer une fuite d'informations.
Surveillance
La surveillance permet d'analyser les événements afin d'identifier des anomalies telles qu'une augmentation brutale du nombre de requêtes, des échecs d'authentification répétés ou une utilisation inhabituelle de certains endpoints.
Codes HTTP
L'utilisation correcte des codes HTTP facilite également le fonctionnement et la surveillance d'une API.
| Code | Signification courante |
|---|---|
| 200 | Requête traitée avec succès |
| 201 | Ressource créée |
| 400 | Requête incorrecte |
| 401 | Authentification requise ou invalide |
| 403 | Accès interdit |
| 404 | Ressource non trouvée |
| 429 | Trop de requêtes |
| 500 | Erreur interne du serveur |
6. Bonnes pratiques pour sécuriser une API
La sécurité d'une API doit être envisagée pendant tout son cycle de vie, depuis sa conception jusqu'à sa mise hors service.
Utiliser HTTPS partout
Toutes les communications contenant des informations sensibles doivent être protégées par HTTPS et une configuration TLS appropriée.
Mettre en place une authentification adaptée
Les endpoints privés doivent utiliser un mécanisme d'authentification adapté au contexte. Les mots de passe et secrets doivent être correctement protégés.
Contrôler les autorisations sur chaque ressource
L'API doit vérifier qu'un utilisateur possède réellement l'autorisation d'accéder à chaque ressource demandée. Le simple fait d'être authentifié ne donne pas automatiquement accès à toutes les données.
Appliquer le moindre privilège
Chaque compte, application ou service doit recevoir uniquement les permissions nécessaires à son fonctionnement.
Valider toutes les entrées
Les données reçues doivent être validées côté serveur avant d'être utilisées par l'application ou transmises à une base de données.
Limiter les données retournées
Les réponses doivent contenir uniquement les champs dont le client a réellement besoin. Cette approche contribue à réduire l'exposition des données.
Protéger les secrets
Les clés API, mots de passe et jetons doivent être stockés et transmis de manière appropriée. Les secrets présents dans un dépôt public doivent être considérés comme potentiellement compromis et remplacés.
Limiter les requêtes
Un mécanisme de rate limiting doit être envisagé pour les endpoints susceptibles d'être abusés, en particulier ceux liés à l'authentification ou à des opérations coûteuses.
Gérer correctement les erreurs
Les messages d'erreur envoyés au client ne doivent pas révéler inutilement des informations internes comme des chemins de fichiers, des détails de configuration ou des traces complètes d'exceptions.
Journaliser les événements importants
Les événements de sécurité doivent être enregistrés afin de faciliter la détection des anomalies, l'investigation et la réponse aux incidents.
Maintenir les dépendances à jour
Les frameworks, bibliothèques et autres dépendances utilisées par l'API doivent recevoir régulièrement leurs correctifs de sécurité.
Inventorier les API
Une organisation doit connaître les API qu'elle expose. Les anciennes versions et endpoints oubliés peuvent créer des surfaces d'attaque inutiles.
Tester régulièrement la sécurité
Les API doivent faire l'objet de tests de sécurité adaptés : revue du code, tests automatisés, analyse des dépendances et tests d'intrusion autorisés dans un environnement approprié.
Utiliser une API Gateway lorsque cela est pertinent
Une API Gateway peut centraliser certaines fonctions telles que l'authentification, la limitation des requêtes, le routage, la journalisation et l'application de certaines politiques de sécurité.
Checklist de sécurité
- Utiliser HTTPS.
- Authentifier les accès privés.
- Vérifier les autorisations côté serveur.
- Appliquer le principe du moindre privilège.
- Valider les données entrantes.
- Utiliser des requêtes SQL paramétrées.
- Protéger les clés et autres secrets.
- Limiter les informations retournées.
- Configurer un rate limiting adapté.
- Journaliser les événements importants sans enregistrer les secrets.
- Surveiller les anomalies.
- Mettre à jour les dépendances.
- Supprimer ou désactiver les anciennes API inutilisées.
- Tester régulièrement la sécurité.
- Préparer une procédure de réponse aux incidents.
7. À retenir
La sécurité des API regroupe les mécanismes destinés à protéger les interfaces de programmation, leurs fonctions et les données auxquelles elles donnent accès.
Une API sécurisée doit correctement gérer l'authentification et surtout l'autorisation. Un utilisateur authentifié ne doit pouvoir accéder qu'aux ressources pour lesquelles il dispose des permissions nécessaires.
Les entrées fournies par les clients doivent être validées côté serveur. Les accès aux bases de données doivent notamment utiliser des mécanismes sûrs comme les requêtes paramétrées lorsque cela est applicable.
Les communications doivent être protégées par HTTPS, tandis que les clés API, mots de passe et jetons doivent être considérés comme des secrets et protégés en conséquence.
Le rate limiting contribue à réduire certains abus automatisés et l'épuisement de ressources. La journalisation et la surveillance permettent quant à elles d'identifier plus rapidement les comportements inhabituels.
La sécurité doit également prendre en compte l'ensemble du cycle de vie : conception, développement, tests, déploiement, mises à jour, surveillance et retrait des anciennes versions.
Enfin, la sécurité des API repose sur une approche de défense en profondeur. Aucun mécanisme isolé ne suffit : authentification, autorisation, validation, chiffrement des communications, gestion des secrets, limitation des requêtes, journalisation et surveillance doivent fonctionner ensemble.
Auteur : Younes Derfoufi
Lieu de travail : CRMEF OUJDA
Site Web : www.tresfacile.net
Chaine YouTube : https://www.youtube.com/user/InformatiquesFacile
Me contacter : https://www.tresfacile.net/me-contacter/



