La sécurité des APIs est une problématique de premier plan pour les entreprises ouvrant leurs SI au public (Open API). Il existe cependant plusieurs approches et implémentations de la dite sécurité d’API, et toutes ne sont pas efficaces. Trop souvent, en concevant une API, on n’adopte que l’authentification basée sur le basic-auth, api-key ou l’authentification par échange de jetons, tout en négligeant un élément majeur qui est l’identité.

 

Comprendre que l’identité est la clé de la sécurité des APIs

Lorsqu’un utilisateur consomme un service, il doit d’abord attester qu’il est bien qui il prétend être. Dans la plupart des cas d’utilisation, il doit ensuite confirmer qu’il est autorisé à faire l’action qu’il souhaite effectuer. La question clé à se poser : comment encapsuler des informations sur l’utilisateur, ses droits ou son origine de manière utile ? Ne serait-il pas formidable qu’une API puisse savoir qui vous êtes, si elle peut vous faire confiance et si vous pouvez faire ce que vous prétendez être capable de faire ? 

Ces idées sous-tendent l’API Security Maturity Model inventé par Jacob Ideskog, vice-président de Curity, une nouvelle façon d’évaluer la sécurité de votre API. Nous allons explorer rapidement chaque couche de ce modèle pour voir comment et pourquoi les experts en sécurité insistent sur l’utilisation des authentifications et autorisations basées sur l’identité.

L’API Security Maturity Model

L’idée est née comme corollaire du modèle de maturité de Richardson. La chose intéressante à propos de ce modèle de maturité est qu’il ne s’agit pas simplement de différents états de conformité : il représente des mises à niveau cumulatives d’un niveau à l’autre. Chaque nouvelle étape tire parti de nouveaux ajouts et inclut les gains précédents. De la même manière, le modèle de sécurité des API s’appuie sur des niveaux de sécurité, de complexité et d’efficacité toujours croissants. À l’instar du modèle Richardson, il va de la maturité la plus basse à la maturité la plus élevée. 

Dans cet esprit, examinons les niveaux du modèle de maturité de la sécurité des APIs en commençant par le niveau le plus bas et en évoluant vers le plus élevé.

Niveau 0 – Api-key et Basic Auth :

Le niveau 0, qui est le niveau de sécurité adopté par la plupart des APIs, utilise une “Basic-Authentication” ou “Api Key” insérée dans l’en-tête ou le corps de l’URL de la requête HTTP pour vérifier les appels vers les ressources demandées.

Faiblesse : non seulement les clés sont constamment compromises, mais la vérification des clés API repose sur une vérification machine-machine, non liée à l’identité de l’utilisateur. Enfin, cette méthode ne fournit que l’authentification, l’acte de prouver une assertion comme par exemple la validation du couple username:password dans le cas de la Basic Auth. Elle ne couvre pas du tout l’autorisation.

Niveau 1 – Authentification basée sur des jetons : 

Ce niveau, qui s’appuie sur le niveau 0, utilise des jetons pour établir l’authentification. Ils ne sont pas partagés entre entités (utilisateur, machine, application), chaque entité a son propre jeton qui la détermine, ce qui permet par exemple une gestion des accès privilégiés, une distinction des utilisateurs (externes, internes, anonymes …), et d’obtenir un meilleur audit (l’identité de l’utilisateur fait partie de la demande).

Faiblesses : au niveau 1, toute personne possédant un jeton peut consommer une API, ce qui signifie que l’accès privilégié peut être piraté. De plus, le niveau 1 ne couvre que l’authentification, pas l’autorisation. En d’autres termes, cette stratégie ne demande pas ce que vous êtes autorisé à faire. Lorsque vous utilisez uniquement des jetons pour l’authentification, toutes les autorisations deviennent un code personnalisé. Ainsi, les mécanismes personnalisés comme les instructions if doivent être codés. Ce n’est plus le cas dans les niveaux 2 et 3, où vous pouvez utiliser des attributs de jeton pour l’autorisation, généralisant ainsi la logique d’autorisation.

Niveau 2 – Autorisation basée sur des jetons :

Encore une fois, cela s’appuie sur les niveaux 0 et 1, mais ajoute OAuth, une norme d’autorisation qui exige que les demandes des clients soient autorisées par un serveur OAuth pour établir l’identité.

Faiblesse : niveau 2, le système est menacé de décompilation. Lorsque l’identité est intégrée directement dans l’API, des erreurs logiques peuvent être découvertes et exploitées. Le niveau 2 induit également un degré de complexité plus élevé du système, car certains paramètres de consommation/invocation d’une API peuvent dépendre d’autres réponses d’API ou d’autres conditions. Que se passe-t-il lorsqu’une API en appelle une autre qui échoue ? Que se passe-t-il si la demande de données est pleine d’erreurs ? Vous ne pouvez pas toujours supposer que les données transmises d’une API à l’autre sont toujours correctes. Ces réalités provoquent des problèmes de confiance en cascade, devenant facilement un gâchis entremêlé : un « spaghetti de confiance ».

Niveau 3 – Confiance centralisée à l’aide des Claims (revendications) :

Ce niveau de sécurité d’’API le plus avancé s’appuie sur les trois précédents mais ajoute à la fois OAuth et OpenID Connect pour vérifier l’identité.

Faiblesse : la compromission des jetons est toujours un problème. Si le serveur OAuth est compromis, alors tout se brise.

Claims : la sécurité de l’API hautement évoluée basée sur l’identité

La confiance est un concept subjectif. Lors de la conception d’un système de sécurité basé sur des APIs, devons-nous faire confiance aux clés, aux jetons, aux mots de passe, aux machines ou aux utilisateurs eux-mêmes ? La réponse est plus complexe que ne le pensent la plupart des concepteurs d’APIs, et peut être cruciale pour protéger votre plateforme dans son ensemble.

Comme le montre le modèle de maturité de la sécurité des APIs, les APIs très matures font confiance à très peu de sources. Surtout, ces APIs évoluées font confiance à l’émetteur de jetons. Cela ne garantit pas la vérité mais constitue la représentation la plus proche de la validation de l’identité des demandeurs. La standardisation de ce processus supprime le code spaghetti et les efforts inutiles sur le code personnalisé.

L’idéal en matière de sécurité des APIs consiste à faire confiance aux claims, et non aux attributs. Lors de la création d’un système de sécurité  basé sur l’identité et basé sur des claims, n’oubliez pas certaines bonnes pratiques :

  • Organiser les données sensibles uniquement pour qu’elles soient accessibles par le serveur OIDC
  • Inclure les données d’identité dans le jeton, pas les attributs de contexte
  • Jetons opaques pour le public, JWT en interne
  • Limiter l’exposition des données uniquement lorsque le client en a besoin
  • Éviter les règles spécifiques à l’application

Autres points d’attention lors du design d’une API pour une meilleure sécurité :

L’article «The Protection of Information in Computer Systems » de Jerome Saltzer et Michael Schroeder a mis en avant huit principes de conception pour la sécurisation des informations dans les systèmes informatiques : 

Le moindre privilège : une entité ne doit disposer que des autorisations requises pour effectuer les actions pour lesquelles elle est autorisée, et pas plus. Des autorisations peuvent être ajoutées selon les besoins et doivent être révoquées lorsqu’elles ne sont plus utilisées.

Fail-Safe Defaults (Valeurs par défaut de sécurité intégrée) :  le niveau d’accès par défaut d’un utilisateur à n’importe quelle ressource du système doit être « refusé » à moins qu’il n’ait reçu explicitement un « permis ».

L’économie du mécanisme : la conception doit être aussi simple que possible. Toutes les interfaces des composants et les interactions entre elles doivent être suffisamment simples à comprendre.

Médiation complète : un système doit valider les droits d’accès à toutes ses ressources pour s’assurer qu’elles sont autorisées et ne doit pas s’appuyer sur la matrice d’autorisation mise en cache. Si le niveau d’accès à une ressource donnée est révoqué, mais que cela ne se reflète pas dans la matrice d’autorisation, la sécurité est compromise.

Conception ouverte : ce principe souligne l’importance de construire un système de manière ouverte, sans algorithmes confidentiels.

Séparation des privilèges : l’octroi d’autorisations à une entité ne doit pas répondre à une unique condition. Une combinaison de conditions basée sur le type de ressource est une meilleure idée pour éliminer les vulnérabilités qui permettent à un utilisateur de s’accorder des droits supplémentaires.

Mécanisme le moins commun : il concerne le risque de partage d’état entre les différents composants. Si l’on peut corrompre l’état partagé, il peut alors corrompre tous les autres composants qui en dépendent.

Acceptabilité psychologique : elle stipule que les mécanismes de sécurité ne doivent pas rendre la ressource plus difficile d’accès que si les mécanismes de sécurité n’étaient pas présents. Bref, la sécurité ne doit pas peser sur l’expérience utilisateur.

Finalement, il n‘y pas d’approche unique de la sécurité bien que les exigences fondamentales des systèmes soient assez universelles. Le besoin de vérifier l’identité des utilisateurs, le besoin de contrôler l’accès, etc., sont essentiels pour le web moderne et les systèmes qui le pilotent. Par conséquent, choisir la bonne approche pour votre flux de sécurité de données est primordial pour une expérience réussie.

Ressources :
https://curity.io/resources/learn/the-api-security-maturity-model/
https://restfulapi.net/security-essentials/

 

Vous souhaitez en savoir plus ?

contactez nos experts

Partager
Faire suivre