Skip to main content

Comment sécuriser une API REST ?

Écrit par
blog feature snyk container custom base recommendations

27 juin 2024

0 minutes de lecture
How to Secure a REST API

En tant que développeurs, nous travaillons souvent avec des API REST lorsque nous intégrons des systèmes tiers ou connectons des systèmes front-end et back-end au travail. Les API, et en particulier les API REST, sont un élément fondamental des applications web modernes : elles nous permettent de créer, lire, mettre à jour et supprimer des données via HTTP. Toutefois, comme toute technologie, elles présentent leurs propres défis en matière de sécurité. Examinons ces défis et voyons comment sécuriser les applications utilisant des API REST.

Qu’est-ce qu’une API REST ?

Les API REST (Representational State Transfer) reposent sur un ensemble de conventions pour concevoir des applications en réseau. Elles utilisent les protocoles HTTP pour envoyer et recevoir des données et peuvent être utilisées avec tout langage de programmation capable d’envoyer des requêtes HTTP. Elles sont ainsi extrêmement polyvalentes et largement utilisées dans le développement web.

Cette polyvalence en fait toutefois aussi une cible pour les cybermenaces. Vous devez donc toujours donner la priorité au développement de logiciels sécurisés, par exemple en mettant en œuvre les 10 contrôles proactifs de l’OWASP. Sans mesures de sécurité adéquates, les API REST peuvent exposer des données sensibles, voire offrir aux attaquants un point d’entrée pour compromettre votre système.

Menaces courantes pour la sécurité des API REST

Les développeurs doivent connaître plusieurs menaces courantes qui pèsent sur la sécurité des API REST :

  1. Attaques par injection : elles se produisent lorsqu’un attaquant envoie des données malveillantes dans le cadre d’une commande ou d’une requête, trompant l’interpréteur pour qu’il exécute des commandes non souhaitées ou accède à des données non autorisées. Par exemple, une attaque par injection SQL peut manipuler les requêtes de base de données de votre API et entraîner des fuites de données ou des modifications non autorisées.

  2. Authentification défaillante : si les mécanismes d’authentification de votre API sont mal implémentés, des attaquants peuvent usurper l’identité d’autres utilisateurs ou même obtenir des privilèges d’administration. C’est ce qui s’est produit lors de la fuite de données de Reddit en 2018, lorsque des pirates ont réussi à contourner l’authentification à deux facteurs par SMS.

  3. Exposition de données sensibles : les API traitent souvent des données sensibles, comme des identifiants utilisateur ou des informations personnelles. Si ces données ne sont pas correctement protégées, elles peuvent être interceptées ou divulguées, entraînant de graves atteintes à la vie privée.

  4. Absence de limitation du débit : sans limitation du débit, votre API est vulnérable aux attaques par force brute, au cours desquelles un attaquant envoie des requêtes répétées pour deviner des identifiants utilisateur ou surcharger votre système. Ce facteur a joué un rôle déterminant dans l’attaque de Dyn en 2016, qui a mis hors service de grands sites web comme Twitter et Netflix. La limitation du débit est souvent mise en œuvre au niveau du middleware et considérée comme une bonne pratique pour sécuriser les passerelles API.

  5. Dépendances non sécurisées : si votre API s’appuie sur des bibliothèques ou des frameworks tiers présentant des vulnérabilités connues, des attaquants peuvent les exploiter. C’est un problème courant dans les logiciels open source, comme l’a montré la fuite de données d’Equifax en 2017, due à l’exploitation d’une vulnérabilité dans Apache Struts.

Vous pouvez atténuer ces menaces en suivant les bonnes pratiques de sécurité des API REST : utiliser des techniques de codage sécurisé, mettre en place des mécanismes robustes d’authentification et d’autorisation, chiffrer les données sensibles et utiliser des outils comme Snyk Code et Snyk Open Source pour détecter et corriger les vulnérabilités de votre code et de vos dépendances.

Dans les sections suivantes, nous passerons en revue ces bonnes pratiques et verrons comment les mettre en œuvre pour sécuriser vos applications utilisant des API REST.

1. Mettre en place des mécanismes robustes d’authentification et d’autorisation

Pour sécuriser une API REST, la mise en place de mécanismes robustes d’authentification et d’autorisation constitue la première ligne de défense. Elle garantit que seuls les utilisateurs authentifiés et autorisés peuvent accéder aux points de terminaison de l’API.

L’authentification sécurisée consiste à confirmer qu’un utilisateur est bien celui qu’il prétend être. Pour sécuriser une API REST, il est essentiel de garantir la sécurité du processus d’authentification afin d’empêcher les accès non autorisés. Par exemple, en 2019, une fuite de données chez Facebook a exposé les informations personnelles de près de 50 millions d’utilisateurs. Elle était due à un problème dans le mécanisme d’authentification, ce qui souligne l’importance d’une authentification sécurisée.

Snyk Code peut vous aider à détecter les vulnérabilités potentielles d’authentification dans votre base de code, comme les identifiants codés en dur ou l’absence de limitation du débit, qui peut entraîner des attaques par force brute.

Utiliser OAuth 2.0 et les JSON Web Tokens (JWT)

OAuth 2.0 est un protocole qui permet à un utilisateur d’autoriser un site web ou une application tiers à accéder à ses informations sans lui communiquer ses identifiants. Il est largement utilisé pour sa simplicité et sa capacité à évoluer.

Dans le cadre de l’authentification, les JSON Web Tokens (JWT) sont un mécanisme populaire permettant d’échanger des informations de manière sécurisée entre plusieurs parties sous la forme d’un objet JSON. Les informations contenues dans un JWT peuvent être vérifiées et considérées comme fiables, car elles sont signées numériquement.

Voici un exemple d’utilisation des JWT pour l’authentification dans une API REST Node.js :

const jwt = require("jsonwebtoken");

// User login
app.post("/login", (req, res) => {
  // Authenticate user
  // ...

  // Generate JWT
  const token = jwt.sign({ userID: user.id }, "your-secret-key");

  // Return token
  res.json({ token });
});

// Secure endpoint
app.get("/secure", (req, res) => {
  // Get token from headers
  const token = req.headers["x-access-token"];

  // Verify token
  jwt.verify(token, "your-secret-key", (err, decoded) => {
    if (err) {
      return res.sendStatus(403);
    }

    // Access granted
    // ...
  });
});

Bonnes pratiques de gestion des jetons d’accès

Les jetons d’accès sont les clés de votre API et doivent être gérés de manière sécurisée. Voici quelques bonnes pratiques :

  • Expiration des jetons : les jetons d’accès doivent avoir une durée de vie courte. Cela limite les dégâts en cas de compromission d’un jeton.

  • Stockage des jetons : évitez de stocker les jetons d’accès dans le stockage local, car des attaquants peuvent facilement y accéder si l’application est vulnérable aux scripts intersites (XSS). Utilisez plutôt des mécanismes de stockage sécurisés, comme des cookies HTTP-only dont les propriétés de sécurité sont activées (SameSite et Secure, ainsi que HTTP-only, conformément aux bonnes pratiques).

  • Transmission des jetons : transmettez toujours les jetons via des canaux sécurisés. Utilisez HTTPS plutôt que HTTP pour éviter les attaques de l’homme du milieu.

Snyk Open Source peut vous aider à détecter les vulnérabilités dans les dépendances open source utilisées pour gérer les jetons, afin de vous assurer que vos jetons d’accès sont gérés par une bibliothèque sans vulnérabilités de sécurité connues. Pour en savoir plus sur la sécurité des applications et garder une longueur d’avance sur les menaces, créez un compte Snyk gratuit.

2. Sécuriser les données en transit et au repos

La sécurisation des données, en transit comme au repos, est un aspect essentiel de la sécurisation d’une API REST. Cette section vous présente les bonnes pratiques à suivre pour sécuriser les données en transit et au repos.

HTTPS (Hypertext Transfer Protocol Secure) est une mesure de sécurité indispensable pour toute API. Il garantit que les données échangées entre le client et le serveur sont chiffrées et ne peuvent pas être interceptées par des attaquants.

La plupart des fournisseurs cloud et des services d’hébergement vous proposent un certificat SSL gratuit, que vous pouvez utiliser pour activer HTTPS sur votre API REST. Toutefois, si vous devez mettre en œuvre la terminaison SSL dans le code de votre application pour communiquer entre des microservices internes ou pour d’autres raisons, voici un exemple d’activation forcée de HTTPS dans une application Flask à l’aide de l’extension Python Flask-SSLify :

from flask import Flask, request
from flask_sslify import SSLify

app = Flask(__name__)
sslify = SSLify(app)

@app.route('/')
def index():
    return "Hello, World!"

if __name__ == '__main__':
    app.run()

Dans l’extrait de code Python ci-dessus, nous utilisons l’extension Flask-SSLify pour imposer HTTPS dans une application Flask. C’est l’une des façons de sécuriser votre API REST avec HTTPS.

Méthodes de chiffrement des données

Le chiffrement des données est un autre aspect essentiel de la sécurisation d’une API REST. Il garantit que même si un attaquant parvient à accéder à vos données, il ne pourra pas les lire sans la clé de déchiffrement.

L’AES (Advanced Encryption Standard) est une méthode de chiffrement des données très répandue. Il s’agit d’un algorithme de chiffrement symétrique largement utilisé pour sa sécurité et son efficacité.

from Crypto.Cipher import AES
from Crypto.Random import get_random_bytes

key = get_random_bytes(16)
cipher = AES.new(key, AES.MODE_GCM)
plaintext = b'This is a test.'
ciphertext = cipher.encrypt(plaintext)

print('Ciphertext:', ciphertext)

Dans l’extrait de code Python ci-dessus, nous utilisons la bibliothèque PyCryptoDome pour chiffrer des données avec AES, une clé de 128 bits et le mode de fonctionnement GCM (Galois/Counter Mode).

Renforcer la sécurité grâce aux en-têtes HTTP

Les en-têtes HTTP peuvent contribuer à renforcer la sécurité de votre API REST. Des en-têtes comme Content Security Policy (CSP) et X-Content-Type-Options peuvent aider à prévenir les vulnérabilités web courantes.

CSP est un en-tête de sécurité qui aide à prévenir les attaques de scripts intersites (XSS) en contrôlant les ressources qu’une page web est autorisée à charger.

X-Content-Type-Options est un autre en-tête de sécurité qui empêche le reniflage du type MIME, une technique utilisée par les attaquants pour inciter le navigateur à exécuter des scripts malveillants.

@app.after_request
def apply_caching(response):
    response.headers["X-Content-Type-Options"] = "nosniff"
    response.headers["Content-Security-Policy"] = "default-src 'self'"
    return response

Dans l’extrait de code Python ci-dessus, nous définissons les en-têtes X-Content-Type-Options et CSP dans une application Flask.

Je vous recommande vivement de lire cet article sur la façon dont une Content Security Policy peut prévenir les attaques XSS et d’autres vulnérabilités.

3. Valider et assainir les données en entrée

L’une des étapes les plus importantes pour sécuriser une API REST consiste à valider et à assainir les données en entrée. Cette étape est essentielle pour prévenir des attaques comme l’injection SQL.

L’injection SQL est une menace courante qui exploite les vulnérabilités des champs de saisie de données d’une application. Dans ce scénario, un attaquant peut manipuler des requêtes SQL en injectant du code SQL malveillant dans les champs de saisie de l’application, et ainsi accéder aux données sans autorisation ou les manipuler. De même, des attaques par injection NoSQL peuvent se produire lorsqu’un attaquant manipule une requête de base de données NoSQL en injectant du code malveillant dans les champs de saisie de l’application.

L’équipe de recherche en sécurité de Snyk a déjà publié des avis de sécurité indiquant que la célèbre bibliothèque ORM Sequelise était vulnérable aux attaques par injection SQL. Cela souligne une fois de plus l’importance de valider et d’assainir les données en entrée et de surveiller les vulnérabilités de vos bibliothèques open source (vous pouvez utiliser Snyk Open Source gratuitement pour vous y aider).

Mettre en œuvre des techniques de validation des données en entrée

Pour atténuer ces risques, il est essentiel de mettre en œuvre des techniques de validation des données en entrée. La validation garantit que seules les données correctement formatées entrent dans votre système. Par exemple, si l’âge d’un utilisateur doit être un nombre, le système doit rejeter toute entrée qui n’est pas numérique.

Voici un exemple simple de validation des données en entrée en JavaScript :

function validateAge(age) {
  if (isNaN(age)) {
    throw new Error("Invalid input: age must be a number");
  }
}

Mieux encore, utilisez une bibliothèque comme Zod ou Joi pour gérer la validation des données en entrée de manière plus robuste et plus facile à maintenir. Ces bibliothèques définissent un schéma attendu pour vos données en entrée, puis les valident par rapport à ce schéma. Elles sont plus rapides et plus fiables que la rédaction de votre propre logique de validation. Si vous êtes adepte de TypeScript, Zod est un excellent choix, car cette bibliothèque a été conçue pour TypeScript.

En plus de valider les données en entrée, vous devez également les assainir afin de neutraliser tout effet néfaste potentiel des données malveillantes. L’assainissement consiste à supprimer ou à modifier des données pour éviter qu’elles ne soient utilisées à des fins malveillantes.

Voici un exemple simple d’assainissement de données en JavaScript :

function sanitizeString(str) {
  return str.replace(/<[^>]*>?/gm, "");
}

Toutefois, n’allez pas trop loin avec l’assainissement par expressions régulières (RegEx). Ce n’est pas une solution miracle et les attaquants peuvent la contourner. Utilisez plutôt des bibliothèques utilitaires comme validator.js, disponible dans l’écosystème npm, qui fournit de nombreuses méthodes de validation pour différents types de données. Lorsque vous écrivez une expression régulière, vous risquez de manquer certains cas limites et d’introduire une vulnérabilité appelée déni de service par expression régulière (ReDoS). Snyk a déjà publié une analyse détaillée de la vulnérabilité ReDoS de la célèbre bibliothèque UAParser.js.

Valider et assainir manuellement chaque donnée peut être fastidieux. Heureusement, des outils permettent d’automatiser ces tâches. Snyk Code en est un. Snyk Code est une solution d’analyse statique de la sécurité des applications (SAST) qui peut vous aider à identifier et à corriger les vulnérabilités de votre code, notamment celles liées à la validation et à l’assainissement des données en entrée.

4. Utiliser des dépendances sécurisées

Pour sécuriser une API REST, il est essentiel de prêter attention aux dépendances dont votre application a besoin. Dans les sections précédentes, nous avons mentionné plusieurs bibliothèques et frameworks populaires qui se sont révélés vulnérables aux menaces de sécurité.

Dans cette section, nous allons examiner plus en détail les risques liés à l’utilisation de bibliothèques vulnérables, voir comment utiliser Snyk Open Source pour détecter ces vulnérabilités et présenter des stratégies pour maintenir vos dépendances à jour.

Les dangers liés à l’utilisation de bibliothèques vulnérables

Les dépendances sont les briques élémentaires de votre application. Mais tout comme une brique fragile peut compromettre la solidité d’un bâtiment, une bibliothèque vulnérable peut présenter de graves risques pour la sécurité de votre API REST.

Par exemple, la tristement célèbre fuite de données d’Equifax en 2017 a été attribuée à une vulnérabilité dans Apache Struts, un framework open source destiné à créer des applications web Java. Cette fuite a exposé les données personnelles de 147 millions de personnes, soulignant l’importance cruciale de l’utilisation de dépendances sécurisées.

// Example of a vulnerable Apache Struts configuration
<struts>
  <constant name="struts.devMode" value="true" />
</struts>

Dans l’exemple ci-dessus, struts.devMode est défini sur true, ce qui peut exposer des informations sensibles et doit être évité en environnement de production.

Le mode développement (devMode) d’Apache Struts est destiné au développement et au débogage. Lorsque devMode est activé, le framework fournit des journaux plus détaillés, des rapports d’erreurs plus complets et permet de recharger la configuration. Ces fonctionnalités sont utiles pendant le développement, mais elles peuvent exposer des informations sensibles et créer des vulnérabilités si elles sont activées en production.

Par exemple, l’activation de devMode peut entraîner :

  • L’affichage de messages d’erreur détaillés aux utilisateurs, susceptibles de révéler des informations sur la structure de l’application, les technologies utilisées, voire des lignes de code et des chemins précis pouvant être exploités.

  • Le rechargement automatique de la configuration, qui peut être détourné pour modifier le comportement de l’application sans avoir à la redémarrer.

  • Une consommation accrue des ressources due aux journaux et au traitement supplémentaires, ce qui peut nuire aux performances et à la stabilité.

Par conséquent, il est recommandé de définir devMode sur false dans les environnements de production afin de limiter ces risques.

Détecter les dépendances vulnérables avec Snyk Open Source

Pour limiter les risques liés à l’utilisation de bibliothèques vulnérables, il est essentiel de disposer d’un système robuste pour détecter et gérer ces vulnérabilités. C’est là qu’intervient Snyk Open Source.

Snyk Open Source vous aide à identifier et à corriger les vulnérabilités de vos dépendances open source. Il s’appuie sur une base de données complète de vulnérabilités connues et surveille en continu vos dépendances pour vous signaler tout nouveau risque.

# Example of using Snyk Open Source to scan your project for vulnerabilities
snyk test

Dans l’exemple ci-dessus, la commande snyk test analyse votre projet à la recherche de vulnérabilités et vous propose des conseils concrets pour y remédier. Les résultats de l’analyse s’affichent dans votre terminal (ou dans le tableau de bord Snyk si vous utilisez l’interface web de Snyk) et indiquent les détails des vulnérabilités, leur gravité et les correctifs suggérés. Voici un exemple de résultat pour une application Java Spring qui utilise une version vulnérable d’Apache Struts :

Testing /path/to/your/project...

✗ High severity vulnerability found in org.apache.struts:struts2-core@2.3.20
  Description: Remote Code Execution
  Info: https://snyk.io/vuln/SNYK-JAVA-ORGAPACHESTRUTS-31560
  Introduced through: org.apache.struts:struts2-core@2.3.20
  From: org.apache.struts:struts2-core@2.3.20 > org.apache.struts:struts2-core@2.3.20
  Remediation:
    Upgrade direct dependency org.apache.struts:struts2-core@2.3.20 to org.apache.struts:struts2-core@2.3.24

Tested 123 dependencies for known vulnerabilities, found 1 vulnerabilities, 1 vulnerable paths.

Stratégies pour maintenir vos dépendances à jour

Maintenir vos dépendances à jour est essentiel pour sécuriser votre API REST. Voici quelques stratégies pour les gérer efficacement :

  1. Vérifiez régulièrement les mises à jour : Prenez l’habitude de vérifier régulièrement si des mises à jour sont disponibles pour vos dépendances. Vous pouvez le faire manuellement ou utiliser des outils comme Snyk pour automatiser le processus.

  2. Adoptez une stratégie de gestion des versions : Choisissez une stratégie qui concilie l’accès aux dernières fonctionnalités et la stabilité de votre application. Le versionnage sémantique est une approche courante qui utilise des numéros de version pour indiquer la nature et l’ampleur des changements.

  3. Automatisez les mises à jour lorsque c’est possible : L’automatisation des mises à jour des dépendances vous fait gagner du temps et réduit les risques d’erreur humaine. Vous pouvez configurer Snyk pour ouvrir automatiquement des demandes de tirage concernant des mises à niveau et des correctifs sans risque.

# Example of using Snyk to automate dependency updates
snyk monitor

Dans l’exemple ci-dessus, la commande snyk monitor surveille votre projet en continu et ouvre automatiquement des demandes de tirage concernant des mises à niveau et des correctifs sans risque. En appliquant ces bonnes pratiques, vous éviterez que vos dépendances ne deviennent le maillon faible de la sécurité de votre API REST. N’oubliez pas : pour savoir « comment sécuriser une API REST », chaque détail compte, et des dépendances sécurisées sont une pièce essentielle du puzzle.

N’oubliez pas que sécuriser votre API REST ne consiste pas seulement à valider et à assainir les données saisies. C’est un processus continu qui nécessite une surveillance et des mises à jour régulières. En suivant ces bonnes pratiques et en utilisant des outils comme Snyk, vous pouvez considérablement renforcer la sécurité de votre API REST.

Prêt à sécuriser votre API REST ? Inscrivez-vous à Snyk dès aujourd’hui.

Lire la suite

Blog

Les modèles de pointe ont trouvé les vulnérabilités. Seul l’attaquant a trouvé les chaînes d’exploitation.

L’analyse statique a détecté les failles, mais seuls des tests d’attaque en conditions réelles ont prouvé comment elles pouvaient être enchaînées pour provoquer des compromissions. Comparaison d’Evo COS, de Claude Security et de Claude Code Security.

feature insights context
Blog

Les attaques autonomes sont déjà là. La défense doit suivre leur rythme.

Les attaquants autonomes réduisent la fenêtre de défense. Découvrez comment la découverte, la correction, la validation et la prévention continues peuvent aider les équipes de sécurité à suivre le rythme.

Blog

Pourquoi les agents de codage IA créent-ils sans cesse des failles de contrôle d’accès ?

Les agents de codage IA peuvent générer une logique d’autorisation qui compile et passe la revue, tout en exposant les données d’un tenant à un autre. Découvrez pourquoi les failles de contrôle d’accès sont difficiles à détecter et comment les prévenir.