Au programme aujourd’hui :
Sécuriser vos Webhooks en Ruby on Rails par François
Temps de lecture : 5 minutes
Hello les petits Biscuits !
Bienvenue sur la 28ème édition de Ruby Biscuit.
Vous êtes maintenant 540 abonnés 🥳
Maintenant Ruby biscuit, c’est aussi votre meilleur allié pour recruter des devs Ruby !
Si vous n’avez pas encore rejoint le club, RDV sur https://recrutement.rubybiscuit.fr
Bonne lecture.
Sécuriser vos Webhooks en Ruby on Rails
Dans le développement d’applications web, les webhooks sont un mécanisme courant pour recevoir des notifications externes sur des événements spécifiques. Par exemple, une application peut recevoir un webhook de service tiers de signature électronique pour l'informer lorsqu'un document a été signé. Cependant, sans mesures de sécurité appropriées, les webhooks peuvent être exploités, exposant ainsi votre application à des risques de sécurité.
Dans cet article, nous allons passer en revue un certain nombre de techniques disponibles pour sécuriser les webhooks. Ensuite nous verrons une mise en pratique avec les webhooks de Dropbox Sign. Nous verrons comment mettre en pratique trois techniques pour sécuriser les webhooks dans une application Ruby on Rails : la vérification des adresses IP, l'utilisation d'un secret partagé (HMAC), et les strong parameters pour filtrer les données entrantes. Ces pratiques garantiront que seules les requêtes authentiques et sécurisées seront traitées par votre application. Enfin nous verrons comment tester ces 3 mesures de sécurité avec Rspec.
Comprendre les Méthodes de Sécurisation des Webhooks
Avant d'entrer dans l'implémentation, voyons quelques méthodes disponibles pour la sécurisation des webhooks :
Appeler le service : Même lorsqu'ils sont sécurisés, les webhooks ne sont pas adaptés pour transmettre des informations sensibles. Une façon de sécurisé l’utilisation des webhooks est de seulement les utiliser pour être informé d’un événement pour une ressource et ensuite d’appeler le service externe via une API pour connaitre l’état de cette ressource. (voir exemple dans la section suivante)
Vérification des IPs : Restreindre l’accès aux webhooks uniquement à certaines adresses IP. Cela permet de s’assurer que les requêtes proviennent d’une source autorisée, comme un service tiers de confiance (Dropbox Sign dans cet exemple).
Vérification du Secret (HMAC) : Un secret partagé ou un HMAC (Hash-based Message Authentication Code) permet de valider que la requête n'a pas été altérée et qu'elle provient bien de la source prévue.
Strong Parameters : Filtrer les données entrantes pour s'assurer qu'elles correspondent aux attentes et éviter les injections de données non désirées ou malveillantes.
Timestamp pour prévenir les attaques par rejeu (Replay Attacks) : En incluant un timestamp dans la requête du webhook, vous pouvez vérifier que l'événement n'est pas ancien et qu'il n'a pas été rejoué. Si l'horodatage dépasse un certain seuil (par exemple, 5 minutes), la requête est rejetée.
Chiffrement des données envoyées : Chiffrer les données transmises via les webhooks, notamment lorsqu'elles contiennent des informations sensibles, garantit que seules les parties autorisées peuvent les lire. Cela peut être réalisé avec HTTPS ou en chiffrant manuellement les payloads.
Utiliser HTTPS et la vérification SSL : GitHub vérifie les certificats SSL lors de la transmission des webhooks et il est fortement recommandé de laisser cette vérification activée. Cela attenue les risques d’écoutes clandestines (eavesdropping) et les attaques de l'intercepteur (man-in-the-middle MITM), où un attaquant peut intercepter et modifier la donnée avant de la transmettre.
Voir plus sur Introduction to Webhook Security - Docs
Appeler le service tiers après reception du webhook
Comme mentionné dans la section précédente, les webhooks ne sont pas la méthode de communication la plus sécurisée et les données transférées sont sensibles (exemple les données bancaires). Par conséquent, certains fournisseurs de service comme Swan n'utilisent pas de webhooks pour envoyer des informations sensibles qui nécessitent une authentification pour être affichées. Le webhook inclut uniquement une notification indiquant qu'un événement s'est produit et une id de ressource afin de pouvoir la retrouver. Il faut ensuite utiliser l'API pour obtenir les informations. On peut visualiser cela dans le graphique ci dessous :
Sécurisation grâce aux fonctionnalités fournies
Tous les fournisseurs de service tiers mettant à disposition des webhooks ne fournissent pas de mesures de sécurité, mais beaucoup le font. Les contrôles de sécurité mis à disposition par le fournisseur de webhook permettent de valider l'authenticité des échanges et à empêcher leur falsification. Cependant, la plupart des fournisseurs n'exigent pas de la part des applications consommants leur service qu'elles utilisent la sécurité qu'ils fournissent. C'est aux développeurs de lire la documentation du webhook du fournisseur pour savoir quelles options sont disponibles, les comprendre, puis les mettre en œuvre.
Implémentation en Ruby on Rails
Dans cet exemple, nous allons implémenter un contrôleur webhook pour Dropbox Sign, avec les trois couches de sécurité suivantes : la vérification d'IP, le HMAC, et les strong parameters.
Code du Contrôleur
Explications :
Vérification d'IP : Le filtre
verify_ip_address
s'assure que la requête provient bien des IPs autorisées définies dans la constanteALLOWED_IPS
.Vérification HMAC : La méthode
verify_secret
utilise un secret (clé API) pour vérifier la signature de la requête. Cela garantit que la requête provient bien de Dropbox Sign et qu'elle n'a pas été modifiée.Strong Parameters : Nous utilisons
webhook_payload
pour filtrer et limiter les données aux seuls paramètres attendus, ce qui empêche l'injection de données non désirées.
Voir la documentation de Dropbox Sign pour plus de détail : Events Walkthrough | Dropbox Sign for Developers
Rspec tests
Il est important de tester les vérifications, notamment pour s’assurer que seules les IPs autorisées et les requêtes valides sont acceptées.
Voici un exemple de tests :
Ce que fait ce test :
Il simule lorsque tout va bien.
Il simule des requêtes venant d’une IP autorisée et d’une IP non autorisée.
Si l'IP est autorisée, le webhook est traité avec succès.
Si l'IP n'est pas autorisée, une réponse "not found" est renvoyée, empêchant la requête d'être traitée.
Il simule des requêtes avec un secret valide et invalide.
Si le secret est valide, le webhook est traité avec succès.
Si le secret n’est pas valide, une réponse "not found" est renvoyée, empêchant la requête d'être traitée.
Conclusion
La sécurisation des webhooks est cruciale pour protéger vos applications contre les attaques et les abus. En combinant la vérification des adresses IP, l’utilisation de secrets partagés et le filtrage des paramètres, vous vous assurez que seules les requêtes authentiques et sûres sont traitées par votre application.
Repo associé : https://github.com/francoisedumas/basic_app_esbuild
Pour aller plus loin
Vous trouverez sur ma chaine YouTube de nombreux sujet technique que j’explore et explique. Kokori Kodo
— François