L'OWASP Top 10 API - 2023

Dans le monde du web, le développement d’API web est en constante augmentation depuis des années. Cela s’explique par de multiples raisons, comme la multiplication d’architectures orientées services ou encore l’intégration de nouvelles applications plus rapides. L’avènement des objets connectés contribue également à cette tendance.

Ces avantages ont également leurs lots d’inconvénients, la principale est l’élargissement de la zone d’attaque, car on passe d’applications web générées coté serveur (Server Side Rendering) à un développement où l’on découple le client et le serveur.

Face à la multiplication des attaques sur les applications web, l’OWASP, pour Open Web Application Security Project, dresse tous les 4 ans un Top 10 des risques les plus rencontrés sur les applications web, les API web ou même sur mobile.

💡 Focus mot clé : En sécurité, un risque est défini par la probabilité qu’une vulnérabilité soit exploitée, multipliée par la gravité potentielle de l’exploitation de cette vulnérabilité.Exemple -très- simplifié : le risque de prendre l’avion est faible, car ces derniers sont très lourdement contrôlés (probabilité d’accident très faible), malgré une gravité élevée en cas d’accident.

Commençons alors à détailler les 10 risques identifiés par l’OWASP. A chaque fois nous y trouverons une brève description du risque, un scénario d’attaque, volontairement simple, pour s’imaginer les enjeux et quelques conseils de développement.

Pour plus de détails, vous pouvez consulter les travaux officiels de l’OWASP ici : https://owasp.org/API-Security/editions/2023/en/0x03-introduction/

1. Broken object level authorization (BOLA)

Héritant de la vulnérabilité Insecure Direct Object Reference, on parle ici d’un défaut lors de la vérification de l’autorisation. Les APIs exposent des données qui sont facilement interrogeables à travers des routes dédiées et des identifiants (exemple : /user/25156 ou encore /invoices/854).

Lorsqu’une requête est effectuée sur une API en vue de récupérer des données, l’API doit vérifier que le requérant (utilisateur ou application) est bien autorisé à lire les données. Cela peut passer par plusieurs mécanismes, comme le contrôle d’accès basé sur le rôle (RBAC).

Le risque ici est l’autorisation n’est pas complètement gérée, ce qui peut donner accès en lecture à des données où il n’a pas l’autorisation. La gestion des autorisations peut devenir complexe suivant l’augmentation du type de données / nombre de rôles et l’erreur humaine est toujours possible.

Scénario d’attaque

Nous disposons d’une API /invoices/<ID>. Les factures sont liées à des entreprises et des personnes. Cependant, si le contrôle est mal réalisé (vérification que la requête appartient bien à l’entreprise liée à la facture), il serait possible de récupérer des factures. Pire encore, si l’ID est un nombre incrémental, il serait possible d’énumérer et récupérer toutes les factures de l’API.

Conseils

  • La route /users est souvent sensible, utilisez /me au lieu de /users/<ID> pour récupérer les données personnelles de l’utilisateur courant
  • Intégrer du contrôle d’accès dans vos tests automatisés (un accès non autorisé doit renvoyer un code HTTP 403)
  • Préférer refuser les accès par défaut et donner les droits aux utilisateurs/rôles (principe du moindre privilège)
  • Utiliser des UUID (123e4567-e89b-12d3-a456-426652340000) au lieu d’ID incrémental

2. Broken Authentication

Cette fois-ci, c’est l’authentification qui est en jeu. Pour rappel, cette notion concerne l’identification d’un utilisateur (et pas ses droits, tel que mentionné précédemment). L’authentification “cassée” est le deuxième risque identifié par l’OWASP.

Le vrai impact ici est qu’un attaquant se fasse passer pour un utilisateur, usurpant alors ses droits. Cela passe par une ou plusieurs vulnérabilités techniques lors du processus d’authentification, comme :

  • Un jeton JWT mal contrôlé (plus d’informations ici)
  • Le bruteforce du mot de passe sur un point de terminaison permettant l’authentification
  • Politique de mot de passe faible

Scénario d’attaque

Nous avons un site web gérant l’authentification par un token JWT, sauvegardé dans les cookies du navigateur web. La vérification de la validité du token a été implémentée directement par le développeur, et ce dernier décode le token pour extraire l’algorithme de hashage de la signature. Il est alors possible de forger un token valide en utilisant le claim “alg” à “none”.

Conseils

  • Ne pas réinventer la roue mais utiliser des bibliothèques dédiées et rodées (exemple : utiliser Passport sous NodeJS)
  • Mettre en place un rate-limiter pour limiter le nombre de requête et éviter les attaques par brute-force
  • Comprendre parfaitement les mécanismes d’authentification, prendre le temps de se former et assimiler les concepts

3. Broken Object Property Level Authorization

La combinaison de deux items d’OWASP Top 10 2019 : Excessive Data Exposure et Mass Assignment.

Ici, c’est là le défaut d’autorisation au sein des propriétés d’un objet qui est en jeu, que ce soit en lecture avec le retour de données sensibles non appropriées (Excessive Data Exposure) ou en écriture (Mass Assignment).

Scénarios d’attaque

Excessive Data Exposure : Un utilisateur utilise une requête SELECT * FROM users pour récupérer les données des utilisateurs (id, pseudo, role). Une évolution fait ajouter un mot de passe dans cette même table. Si la requête n’est pas modifiée, l’API va désormais exposer le mot de passe des utilisateurs.

Mass Assignment : Une API permet de modifier les données de notre profil utilisateur, qui envoie le body { pseudo : "test" }. Cependant, en inspectant le trafic réseau, l’attaque peut tenter d’envoyer { pseudo : "test", role : "admin" }. L’API peut contrôler que l’utilisateur est autorisé à écrire, mais doit vérifier quels champs il peut écrire. Cela peut se produire lors de l’utilisation d’un ORM, par exemple :

// désérialisation du contenu en entrée const user = new db.User(req.body); // sauvegarde de l'objet en base de données user.save()

Conseils

  • Spécifiez explicitement quels champs des objets doivent être retournés (évitez donc les méthodes comme toString())
  • Utiliser un schéma de réponse (DTO)
  • Évitez les fonctionnalités qui connectent directement l’entrée utilisateur aux variables

4. Unrestricted Resource Consumption

Son nom est plutôt clair : on parle ici du problème de la gestion des ressources du serveur. Savoir si l’API est sensible à ce risque peut venir de plusieurs facteurs : la RAM du serveur, la taille maximum des fichiers lors de l’upload, le timeout du serveur, nombre d’opérations maximum à effectuer lors d’une seule requête HTTP GraphQL (Batching GraphQL) et autre.

Ce risque englobe également les risques liés à la consommation de fonctionnalités payantes accessible à travers des API.

Scénario d’attaque

Une entreprise a développé une application web qui affiche une carte et effectue des requêtes de géocoding qui sont payantes. Si le développeur requête directement l’API de géocoding, la clé API est embarquée dans le code client. Cela signifie que n’importe qui peut récupérer la clé et écrire un script qui va requêter l’API avec cette clé… Qui peut engendrer des coûts importants.

On pourrait également imaginer la même chose lors d’envoi de sms en cas de mot de passe perdu. Si aucune limite de requête par minute n’est mise en place, l’attaquant pourrait déclencher l’envoi de milliers de sms, payants pour l’entreprise.

Conseils

  • Mettre en place un rate limiter sur les routes API sensibles
  • Limiter la taille des fichiers pouvant être téléversés
  • Déployer un proxy web pour contrôler l’appel aux fonctionnalités payantes (et, si possible, mettre en place un cache coté serveur)
  • Utiliser des limiters à la scabilité des infrastructures Cloud

5. Broken Function Level Authorization

Ce risque est similaire à Broken Object Level Authorization, sauf qu’on parle ici de l’accès à certaines fonctionnalités qui sont mal protégées. Comme le BOLA, ce risque provient de la complexité à hiérarchiser et configurer les rôles et droits utilisateurs.

Scénario d’attaque

Une route admin qui n’est appelée que si l’on est connecté en tant qu’admin mais qui peut être découverte par une attaque en “devinant” la route (comme /api/admin/users/all), et qui a été mal protégée, donnant accès à des utilisateurs non autorisés.

Conseils

  • Idem que BOLA

6. Unrestricted Access to Sensitive Business Flows

C’est ici un cas simple à comprendre mais difficile à anticiper, qui n’est pas forcément lié à des malfaçons de développements. Ce risque est lié à toutes les conséquences qui peuvent être induites si un attaquant utilise de manière excessive des fonctionnalités de l’application, comme la création de tickets, commentaires, réservations etc…

Scénario d’attaque

  • Un restaurant dispose d’une application pour réserver une table en ligne. Un attaquant pourrait alors écrire un script pour réserver toutes les tables, rendant les prochaines réservations impossibles.

Conseils

Note : Il est très difficile de protéger à 100%. Cependant, ces mesures auront pour but de ralentir / décourager les potentielles attaques

  • Utiliser l’empreinte de l’appareil qui émet la requête pour n’en autoriser qu’une
  • Mettre en place une détection d’humain : captcha, modèle de frappe, mesure du temps entre différentes actions (mise en panier ⇒ validation ⇒ achat).
  • Utiliser les IP pour filtrer, en bloquant les IPs connues des nœuds VPNs / Tor

7. Server Side Request Forgery

Ce risque arrive quand l’attaquant contrôle les urls qui seront appelées par le serveur. Grâce à cela, l’attaque peut se servir de l’application web comme d’un proxy pour interroger différentes applications web dans le même réseau.

Scénarios d’attaque

  1. Si une application web prend en entrée une url pour changer une photo de profile d’un utilisateur, l’attaquant pourrait utiliser l’adresse localhost:<port> pour scanner le réseau interne (et donc les ports ouverts sur la machine) en fonction de la réponse
  2. Un service web peut être configuré pour appeler un webhook, et va logguer la réponse HTTP pour qu’elle soit consultable par le développeur. Si le serveur autorise de mettre des ip locales ou privées, il sera possible d’envoyer des requêtes HTTP vers des services normalement non accessible à l’extérieur (comme une console admin non protégée) et voir le contenu de la page html.

Conseils

  • Désactiver les redirections HTTP
  • Ne pas communiquer les réponses des requêtes HTTP
  • Valider le protocole et les ports de destination
  • Utiliser une liste d’urls autorisées, et / ou une liste d’url non autorisées (exemple : bloquer les ip et les domaines pointant vers le réseau local)

8. Security Misconfiguration

Les systèmes logiciels peuvent vite devenir complexes à mesure de l’ajout de composants : infrastructure, système de déploiement automatisé, réseau etc… La pile totale des technologies peut des fois faire intervenir différents métiers, qui peuvent faire des erreurs de configuration ou ne pas suivre les bonnes pratiques de sécurité. Cela peut alors entraîner une multitudes d’attaques possibles.

Scénario d’attaque

  1. Un serveur apache qui autorise l’exécution de toutes les extensions de code php (exemple : .phtml). Si une fonctionnalité d’upload de fichier n’empêche que les fichiers contenant “.php”, l’attaquant pour exécuter du code sur le serveur en connaissant le répertoire destination.
  2. Dans un cadre de requêtes CORS, le serveur renvoi systématiquement l’origine de l’appelant dans l’entête [Access-Control-Allow-Origin](<https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Access-Control-Allow-Origin>) , pouvant conduire à des attaques CSRF si l’attaque arrive à faire venir les visiteurs sur une copie du site qu’il contrôle.

Conseils

  • Créer une tâche dédiée à la revue des configurations et le respect de leurs bonnes pratiques de sécurité (la majorité des systèmes disposent d’une page à cet effet dans leurs documentations)
  • Faites attention aux différents verbes HTTP utilisés, désactiver ceux qui ne sont pas utilisés
  • Prenez le temps de comprendre et implémenter les bonnes entêtes HTTP, utiliser https://securityheaders.com/ pour les vérifier

9. Improper Inventory Management

Au fur et à mesure qu’une APIs se développe, le nombre de ses points de terminaisons, arguments, ou encore de versions augmente. En tant que développeur d’API, il est important de tenir un inventaire de toutes les routes qui sont exposées. Le risque ici est de continuer à rendre accessible des routes dépréciées, non protégées ou souffrant de patch, qui peuvent devenir une brèche dans le système ou encore exposer des données qui ne devraient pas l’être.

Scénarios d’attaque

  • Un rate limiter qui a été mis en place sur un environnement en version 2, mais pas en version 1, qui n’est plus utilisé officiellement. Cependant, une attaque peut réussir à découvrir cette route (fuzzing, guessing etc..) et lancer une attaque de brute force, le rate limiter n’étant pas installé sur cette version.

Conseils

  • Documenter toutes les endpoints et version de l’API
  • Ne plus exposer les routes inutilisées
  • Ne pas utiliser des données de production en dehors d’environnement de préproduction (dans le cas où c’est inévitable, mettre en place les même mesures de sécurité)

10. Unsafe Consumption of APIs

Les applications web utilisent souvent des données de tierces APIs et injectent directement ces données dans leurs traitements. Cependant, ces données étant considérées comme “sûres”, ne sont pas nettoyées ou contrôlées.

Scénarios d’attaque

  1. Un serveur va récupérer des données d’une API tiers qu’il va ensuite stocker en base. Une attaque pourrait s’attaquer au fournisseur pour modifier les données renvoyer en intégrant une charge utilise pour une injection SQL. Cette dernière pourrait alors être déclenchée lors du traitement par le serveur.
  2. Un serveur renvoi des données personnelles sur une API. Si cette dernière a été corrompue, elle peut retourner une erreur 308 (Permanent Redirect) qui va faire envoyer les données vers une autre API, contrôlée par l’attaque

Conseils

  • Évaluer le niveau de sécurité des API tiers
  • Communiquer toujours en TLS
  • Valider et nettoyer les données avant de les utiliser

En conclusion, on observe qu’il est primordial d’au moins sensibiliser les développeurs et développeuses à ces différents risques. Cela pourra leur donner des outils et des réflexes à adopter lors des développements d’API.

Pour aller plus loin, nous recommandons fortement de former les équipes techniques aux rudiments du développement sécurisé.