Sécurisation des APIs / services : les échanges

Thomas Raffin
neoxia
Published in
6 min readNov 15, 2019

Avec la multiplication des API, leur sécurité est devenue un élément clé du SI. Loin de balayer l’intégralité des possibilités offertes par les différentes solutions de management d’API, telles que Apigee de Google par exemple, cet article a pour but de présenter des réponses le plus à jour possible aux problématiques récurrentes. Ces éléments sont issus de cas concrets et de l’expérience des consultants Neoxia au cours de leurs différents travaux d’API-sation ces dernières années.

Cet article est le 1er d’une série relative à la sécurisation des API et services. Il portera plus particulièrement sur la sécurisation des échanges.

Sécuriser les échanges API

Comme l’illustre le schéma suivant, il y a classiquement plusieurs intervenants dans un processus de consommation d’API.

Nous retrouvons au centre un reverse proxy (ou à minima une DMZ) qui est un pré-requis avant de pouvoir commencer à travailler sereinement et implémenter la moindre mesure de protection efficace du SI. Il est en effet l’unique point d’entrée/sortie et reste l’extérieur du SI.

Nous allons tout d’abord nous intéresser à la communication entre le proxy et l’application cliente (Northbound), puis entre le proxy et le(s) backend(s) (Southbound), et enfin l’authentification de l’application cliente ou de l’utilisateur final.

Interface Northbound

Il est possible d’agir à plusieurs niveaux pour protéger les échanges entre les applications clientes et les proxies qui publient des API.

La mesure la plus évidente est de ne permettre que des échanges chiffrés, à savoir en HTTPS (Hyper Text Transfer Protocol Secure), et n’utilisant que des versions à jour des différents algorithmes de chiffrement.

Pour rendre le canal de communication opaque pour tout intervenant extérieur, on utilisera le protocole TLS (Transport Layer Security), successeur de SSL (Secure Sockets Layer) aujourd’hui obsolète. Il faudra bien désactiver toutes les versions obsolètes et utiliser des paramètres de chiffrement robustes. Si les certificats sont signés par une autorité de certification (CA), alors l’application cliente peut vérifier leur validité et la correspondance avec le domaine utilisé, donc l’identité du proxy. Les certificats et clés publiques peuvent aussi être échangés au-préalable. Ainsi l’application cliente est certaine d’être en communication avec le proxy attendu. On parle alors de 1-way TLS.

Il est aussi possible de mettre en place du 2-way TLS sur l’interface Northbound. Mais pour des raisons de simplicité, on se limite généralement 1-way ici (les APIs sont ainsi utilisables par tout développeur, avec un délai de lancement rapide). Le mécanisme de 2-way TLS nous intéressera dans la partie suivante.

Interface Southbound

La liaison Southbound concerne le lien entre le proxy et un ou plusieurs backends. Les mécanismes vus précédemment sont à mettre en oeuvre : HTTPS et X-way TLS.

Une autre mesure simple et souvent disponible consiste à définir un filtrage par liste blanche des IP côté backend. Il ne faut pas considérer que cela puisse garantir que seul le proxy aura accès au backend. En effet même sans parler d’usurpation d’IP, dans la plupart des cas, plusieurs proxies, voire plusieurs services, utilisés par différents clients peuvent utiliser ces IP. C’est notamment le cas dans les offres Cloud publiques. Cette mesure n’est donc pas suffisante (ni nécessaire), c’est un simple plus.

Etant donné la nature des applicatifs, les technologies, les compétences des intervenants, etc… habituellement mises en oeuvre des 2 côtés de ce lien, il est possible d’aller plus loin concernant l’authentification, et ce en permettant au backend de s’assurer que le client est bien celui attendu.

Selon les fournisseurs, le protocole 2-way TLS peut par exemple être utilisé. Il s’agit là d’une authentification mutuelle entre le client et serveur : lors du handshake préalable ils vont échanger leur certificats respectifs et les vérifier. Cette approche est plus sécurisée car plus restrictive qu’un VPN par exemple, qui autoriserait une zone et non un proxy seulement.

S’il n’est pas possible de mettre en place TLS, une autre possibilité, est d’utiliser un mécanisme de signature des requêtes. Il existe plusieurs protocoles pour cela (à base de secret partagé, de certificats publics/privés ou d’autres algorithmes). Le processus est souvent le même : à la requête envoyée par le Proxy au Backend, on ajoute une chaîne (dans un Header HTTP par exemple) que le Backend saura vérifier.

AWS (Amazon Web Service) propose aujourd’hui le protocole Signature Version 4 pour la quasi-totalité de ces services.

Authentifier l’application cliente ou l’utilisateur

Toutes ces dispositions seront sans effet pour limiter l’utilisation des backends si l’accès à l’API n’est pas contrôlé. Diverses formes d’authentification sont possibles afin d’autoriser une application consommatrices de l’API parmi d’autres (avec un compte de service) ou un utilisateur final.

Les problématiques auxquelles elles doivent répondre peuvent être diverses :

  • la solution doit être universelle car les API peuvent être consommées par des applications variées en terme de technologie ;
  • elle doit permettre une utilisation stateless côté serveur ;
  • elle doit prendre en compte des contraintes comme le CORS (Cross-Origin Resource Sharing) ou les attaques de type XSRF ou CSRF (Cross-Site Request Forgery).

Parmi les mécanismes les plus simples, nous retrouvons Basic Auth, qui consiste à faire transiter les identifiants sous une forme codée à chaque requête. Tout aussi simple, celui de l’API Key consiste à passer un secret prédéfini et partagé, là aussi, lors de chaque appel. Ces méthodes ont pour inconvénient de faire transiter systématiquement des secrets entre l’application et le proxy, sans parler des contraintes de stockage et de protection. Elles ne devraient pas être utilisées.

La solution à l’état de l’art est OAuth2. Il s’agit d’un framework de délégation d’autorisation qui consiste à échanger des tokens une fois la phase d’authentification terminée. Il est fiable (mais tout dépendra de sa bonne implémentation) et répond à de nombreux cas d’utilisation : autorise-t-on une application ou un utilisateur final ? Ce framework est souvent utilisé pour authentifier les utilisateurs. La couche OpenId Connect est arrivée pour résoudre ce cas d’utilisation.

Voici un schéma expliquant une partie des choix possibles :

A noter que pour le très répandu cas qui consiste à vouloir authentifier un utilisateur depuis une Single Page Application, OAuth2 a longtemps recommandé d’utiliser l’Implicit Grant Flow. Ce n’est désormais plus le cas, et il faut utiliser l’Authorization Code Grant Flow avec PKCE (Proof Key for Code Exchange).

La délégation d’autorisation permet aussi de mettre en place du SSO (pour Single Sign-On). Celui-ci consiste en une authentification unique : si l’utilisateur est loggué pour une application, il l’est aussi pour les autres. La phase d’authentification est donc mutualisée. Différentes solutions peuvent permettre de faire cela : SAML ou OpenID Connect.

Pour répondre au besoin de faire transiter des informations entre l’application cliente et l’API (par exemple un identifiant technique ou métier, des informations métier, …), JWT (JSON Web Token) peut être une solution viable. Cette méthode consiste à faire faire passer dans chaque requête un jeton non opaque (car décodable) contenant des données et une signature. Certaines précautions sont à prendre (liste non exhaustive) :

  • ne pas faire transiter d’informations sensibles dans ce token qui pourrait être déchiffré si intercepté,
  • bien vérifier les paramètres de chiffrement (algorithme, force, …),
  • utiliser une durée de validité courte.

Selon les technologies employées et leur mise en oeuvre, l’utilisation de token à usage unique peut aussi être intéressante.

Une fois l’authentification mise en place, une gestion des accès selon des rôles doit être définie et appliquée.

Pour aller plus loin :

--

--