9. Securisation - Yolino/t211-dbox-fm GitHub Wiki
Résumé coaching 9
ANALYSE DE SECURITE
+ Le groupe a effectué et documenté sur le wiki une analyse de sécurité correcte, en identifiant les biens à protéger et en estimant les menaces et les risques associés.
+ Le groupe a identifié des contre-mesures adéquates pour l'ensemble des menaces identifiées.
+ Le groupe connait et documente les limites de son travail de sécurisation (risques résiduels, …)
+ Le groupe a réfléchi au suivi des aspects sécurité du projet tout au long du cycle de vie du projet
+ Un diagramme de flux de données est attendu
SECURISATION
+ Le groupe a mis en place les éléments de sécurité demandés dans le cadre du cours. Le groupe justifie et implémente correctement les mesures de sécurité au niveau du serveur (Utilisation https, version à jour / patchée, réflexion sur le hardening du serveur -par ex : pas d’autre port ouvert-, gestion des connexions et sessions, disponibilité, …), au niveau logiciel ( Librairies / Framework utilisés à jour, XSS, SQLi,gestion/stockage des mots de passe, ... ) et de la DB ( Inaccessible de l’extérieur, permissions / rôles définis adéquatement, backup, …)
VALIDATION DE LA SECURITE
+ Les étudiants ont utilisé des outils extérieurs pour valider la sécurisation de leur site, et présentent les résultats sur le wiki
+ Les étudiants ont compris, interprété et pris en compte les retours donnés par les outils extérieurs et corrigé les failles de sécurité éventuellement identifiées
ASPECTS LEGAUX
+ Le wiki présente les contraintes légales auquel est soumis le site web (notamment RGPD)
+ Le wiki présente ce qui a été mis en place, ou aurait dû être mis en place, pour respecter le prescrit légal (traitement des données, backup, …)
1. Analyse de la sécurité
1.1 Biens à protéger
Code
Notre code source répertorie plusieurs informations qui pourraient nuire à la santé du site. Elles prennent majoritairement la forme de secrets et de variables d'environnement, comme les mots de passe d'accès au panel d'admin, des rôles agissant sur la base de données, ... Nous n'interagissons avec aucun service externe, donc aucune clé API n'est présente.
Base de données
Les seules informations sensibles stockées dans la base de données sont les mots de passe des utilisateurs, étant donné que le reste des informations est public. Il est bien sûr important de maintenir l'intégrité du schéma de données et limiter leur accès en écriture.
Serveurs
Nos deux VPS permettent le déploiement et la présence de l'application sur Internet. Il n'est pas nécessaire d'expliquer pourquoi il sont extrêmement importants pour la survie du projet.
1.2 Risques
Menace | Probabilité | Impact | Risque | Détails |
---|---|---|---|---|
Accès non autorisé via API | Moyenne | Élevé | Élevé | Un utilisateur pourrait forger une requête pour accéder à des contenus ou fonctionnalités restreintes. |
Fuite de données lors des communications inter-serveurs | Moyenne | Élevé | Élevé | Le monitoring utilise HTTP, ce qui pourrait exposer des données sans chiffrement. |
Attaque DDoS (Déni de service distribué) | Moyenne | Élevé | Élevé | Des requêtes massives pourraient rendre l’application ou le serveur inaccessibles aux utilisateurs légitimes. |
Fichiers utilisateurs malveillants | Moyenne | Moyen | Élevé | Des fichiers audio ou images pourraient contenir du code dangereux ou détourner le système. |
Attaque brute-force sur login ou SSH | Faible | Élevé | Moyen | Tentatives répétées d’accès non autorisé à des comptes utilisateur ou administrateur. |
Injection SQL | Faible | Élevé | Moyen | Si des requêtes SQL étaient mal paramétrées, un attaquant pourrait compromettre la base de données. |
Compromission d’un conteneur | Faible | Élevé | Moyen | Une faille dans un conteneur pourrait être exploitée pour compromettre l’ensemble du système. |
Exposition des routes sensibles | Faible | Élevé | Moyen | /admin et /grafana pourraient être trouvées par un tiers malveillant. |
CSRF (Cross-Site Request Forgery) | Moyenne | Moyen | Moyen | Une requête légitime pourrait être détournée à l’insu de l’utilisateur via son cookie de session. |
XSS (Cross-Site Scripting) | Faible | Moyen | Faible | Un script malveillant pourrait s’exécuter dans le navigateur d’un utilisateur via des contenus injectés. |
1.3 Contre-mesures
Menace | Contre-mesure(s) | Implémentée | Détails |
---|---|---|---|
Accès non autorisé via API | Vérification de l'identité de l'utilisateur avant exécution de requête | ✔️ | Présente dans tous les endpoints REST et GraphQL nécessitant une authentification. |
Injection SQL | ORM Django (requêtes paramétrées) | ✔️ | Django utilise automatiquement des requêtes sécurisées via ORM. |
Fichiers utilisateurs malveillants | Validation poussée des fichiers | ✔️ | Via validators.py , vérification de type MIME, taille, extension, FFMPEG pour les audios, Pillow pour les images. |
XSS | Échappement automatique dans Django | ✔️ | Django échappe les caractères potentiellement dangereux dans les templates. |
CSRF | Middleware CSRF Django | ✔️ | Cookie secret généré dynamiquement, avec token unique dans chaque requête POST. |
Attaque brute-force | Fail2Ban + changement de port SSH | ✔️ | Blocage temporaire d'IP après plusieurs échecs, port SSH non standard, clé obligatoire. |
Compromission d’un conteneur | Isolation Docker + pare-feu UFW | ✔️ | Services cloisonnés, limitation des accès inter-conteneurs. |
Exposition des routes sensibles | Authentification TLS client | ✔️ | Accès à /admin et /grafana restreint via certificats TLS clients importés dans le navigateur. |
Fuite de données inter-serveurs | VPN entre serveurs | ✔️ | VPN chiffré utilisé entre le serveur principal et celui du monitoring. |
1.4 Suivi de la sécurisation
La sécurité de l’application est assurée en continu par un système de monitoring intégré, permettant l’analyse du comportement global et la détection d’anomalies. Même si cette surveillance reste simple pour l’instant, elle permet de :
- repérer les erreurs applicatives ou tentatives d’accès non autorisées,
- observer les tendances de trafic ou les actions des utilisateurs,
- centraliser les logs applicatifs et système.
Les administrateurs ont accès à un panel /grafana
sécurisé par certificat TLS client, leur permettant de visualiser les métriques. Les logs des conteneurs, tout comme les logs du serveur web (Nginx) et de Django, sont consultables en cas d’incident.
De plus, un test individuel de chaque requête API a été mené pour valider les contrôles d’accès. Les certificats TLS (serveur et client) sont également vérifiés manuellement à intervalles réguliers.
Enfin, une phase de bug bounty officieuse a été mise en place au sein de la classe, durant laquelle plusieurs collègues ont tenté de repérer des failles. Cette initiative, bien que non rémunérée, a permis une validation réaliste des dispositifs de sécurité.
1.5 Diagramme de flux de données
2. Sécurisation
Application
Authentification par session
Le module django.auth.contrib
nous met à disposition des un modèle User
pour la gestion des utilisateurs, ainsi que des méthodes et fonctions permettant une abstraction élevée sur son fonctionnement. Ce module met bien évidemment en place un système de hashing de mots de passe avec user.set_password()
. Il emploie notamment les middleware Django AuthenticationMiddleware
et SessionMiddleware
afin de vérifier les credentials des utilisateurs, et altérer la réponse HTTP pour y inclure un cookie de session approuvé par Django. Nous employons le backend de gestion de session django.contrib.sessions.backends.db
, et les informations sont donc stockées dans la base de données PostgreSQL.
Contrôles d'accès à l'API
Il est évident que simplement cacher les requêtes d'API au frontend n'est pas suffisant pour assurer la sécurité de l'application, car il est relativement simple de forger des requêtes. Notre endpoint GraphQL et nos endpoints REST implémentent tous (du moins ceux qui demandent des privilèges) un contrôle d'accès vérifiant l'identité de l'envoyeur de la requête ainsi que sa légitimité à exécuter la requête. Ces contrôles d'accès sont bien évidemment effectués avant toute autre logique applicative. Les requêtes privilégiées incluent non exhaustivement la publication et leurs réactions (connexion obligatoire), la modification de contenu (auteur du contenu en question), la connexion et création de comptes (connexion interdite), la consultation du contenu banni et leur revue (modérateurs), la modification du programme radio.
Sanitisation des entrées utilisateur
Nous effectuons des validation des input avant de les employer dans l'application. C'est le cas des fichiers audio et des images, qui peuvent être facilement détournés à des fins malveillantes en bypassant les contrôles de sécurité. Ils passent par plusieurs checks implémentés dans validators.py
, notamment une vérification de l'extension, du type MIME réel, de la taille, et une vérification plus poussée avec Pillow pour les images, avec FFMPEG pour les audios.
CORS
Nous avons limité le Cross-Origin Resource Sharing en spécifiant dans notre configuration les origines de requêtes de confiance. Dans notre cas, il ne s'agit que de dbox-fm.be
, car comme spécifié précédemment, nous n'avons recours à aucun service externe.
CSRF
La protection contre le Cross-Site Resource Forging provient lui aussi de Django, qui place un secret dans le navigateur du client, sous forme d'un cookie. Ce secret est arbitraire et généré dynamiquement par le backend, ce qui empêche des attaques replay, dans lesquelles un attaquant essayerait de rejouer la communication à l'identique.
XSS
Django empêche l'exécution de Cross-Site Scripting grâce à un échappement des caractères dangereux permettant potentiellement d'injecter du JavaScript sur la machine de l'utilisateur. La documentation Django met cependant en garde que ce mécanisme n'est pas infaillible, et qu'il est notamment possible de tirer profit des variables préalablement initialisées dans le template (risque faible/modéré).
Injections SQL
Django met également en place une protection contre les injections SQL, grâce à la paramétrisation des requêtes SQL par défaut. Il est à noter qu'il est possible d'écrire des requêtes SQL soi-même, auquel cas il faudrait faire attention à leur sécurisation, mais ce n'est pas le cas de notre application.
Panel d'admin
Django nous fournit une route /admin
(employant le même mécanisme de session que l'application et nécessitant donc une autorisation) permettant d'accéder aisément à une gestion du contenu de la base de données. Nous disposons de ce fait d'un contrôle beaucoup plus minutieux des informations qui se trouvent sur le serveur. Ce n'est pas une mesure de sécurité à proprement parler, mais ce panel contribue à un potentiel de gestion rigoureuse du site et donc de minimiser l'impact de potentielles attaques.
Monitoring
En parallèle, nous avons mis en place notre propre système de monitoring sur l'application. Comme pour le panel d'admin, il ne s'agit pas d'une mesure de sécurité en soi, mais il y contribue amplement. La surveillance de l'application nous permet de calculer des métriques importantes et d'observer son comportement global. Ce monitoring est toutefois assez rudimentaire en raison de son implémentation récente, et nous prévoyons de rendre celui-ci plus robuste, notamment en surveillant les tentatives d'accès non autorisés et en envoyant des alertes aux administrateurs, ainsi qu'en créant davantage de visualisations.
Infrastructure
Hardening du serveur
Une des mesures importantes est de garder le serveur sécurisé et à jour. Nous menons une politique de hardening, qui implémente un pare-feu strict (UFW), Fail2Ban pour éviter le brute-force, une sécurisation des accès SSH avec obligation d'authentification par clé ainsi qu'un changement de port, et également des mises à jour régulières (toutes les deux semaines).
Conteneurisation
Notre infrastructure est intégralement conteneurisée grâce à Docker, ce qui ajoute déjà initialement un niveau de sécurité élevé, grâce à l'isolation de chaque service et au contrôle de leur exposition de ports et de leurs privilèges. Nous employons des réseaux Docker permettant de limiter les connexions à ce qui est strictement nécessaire. Ces mesures d'isolation permettent de réduire le potentiel d'escalation de privilèges d'une potentielle attaque.
HTTPS
Une autre mesure majeure est la sécurisation de notre trafic applicatif. Notre serveur dispose pour cela d'un certificat TLS signé par Let's Encrypt. Pour aller plus loin, nous avons également automatisé le processus de renouvellement du certificat grâce à un conteneur Certbot lancé périodiquement par un cron job. Le certificat n'est pas un wildcard, ce qui évite également le vol d'identité d'un ou plusieurs services après la compromission d'un premier service.
Certificats TLS clients
Afin d'ajouter un contrôle d'accès plus rigoureux à nos routes privilégiées /admin
et /grafana
, toutes deux assez sensibles, et bien que sécurisées par un mot de passe, il était pour nous nécessaire de camoufler leur accès à l'extérieur. Nous disposions de plusieurs options, la première était d'établir un contrôle d'accès sur base de l'adresse IP, mais est rapidement tombée à l'eau en raison de la grande mobilité de nos appareils. Nous avons ensuite envisagé l'option d'un VPN, qui permettrait de se connecter de manière sécurisée et contrôlée aux routes en question. Nous avons jugé que cette mesure aurait nécessité trop de configuration pour l'importance que nous accordons aux biens protégés. Nous avons finalement opté pour des certificats TLS clients, permettant d'établir une liste des détenteurs d'accès aux deux routes privilégiées.
En ayant principalement suivi ce tutoriel, nous avons successivement créé une autorité de certification ainsi qu'un certificat serveur, des clés de chiffrement et certificats clients, qui ont ensuite été compilés en fichiers .pfx
, pour être importés sur le navigateur des administrateurs. Un seul certificat donne accès aux deux routes, car dans notre cas nous n'avons pas besoin d'encore amplifier la granularité du contrôle d'accès, mais cela pourrait être facilement réalisable. La configuration nginx a dû être modifiée avec la directive ssl_client_certificate
. Une authentification échouée ou inexistante ($ssl_client_verify != SUCCESS
) redirige automatiquement vers l'accueil du site web, comme le font les routes inexistantes.
VPN
Pour sécuriser les échanges entre le serveur principal et le serveur de monitoring, nous avons déployé un VPN servant de tunnel chiffré par lequel les VPS peuvent communiquer librement. Nous avons mis cela en place en raison de l'utilisation d'HTTP par les conteneurs de monitoring, il était de ce fait indispensable de trouver un moyen de chiffrer les paquets.
Utilisateurs non-privilégiés
Appliquant la politique du moindre privilège, nous conférons les accès strictement minimum aux différents acteurs de l'application selon leur rôle. Nous avons créé un rôle non privilégié sur la base de donnée, qui dispose uniquement des accès nécessaires à faire fonctionner l'API (read/write sur les tables principales). Il n'a donc pas de permissions de modification du schéma par exemple.
3. Validation de la sécurité
Chaque requête API a été testée individuellement pour éviter un contrôle d'accès défaillant. La validité des certificats TLS serveur et clients a été assuré manuellement.
De plus, étant donné que notre site fut déployé assez rapidement, nous avons eu l'occasion de disposer d'une période assez longue pour valider la sécurité de l'application et corriger les erreurs présentes. Grâce à un engouement d'un bon nombre de collègues de l'EPHEC pour notre projet, ces derniers ont pu relever des détails qui nous auraient échappé, et nous leur avons également autorisé d'essayer de trouver des failles dans notre système, similairement à un programme de Bug Bounty, qui malgré l'absence de récompenses, leur donne une occasion de pratiquer certaines compétences de penetration testing dans la légalité de notre infrastructure. Cependant, aucune faille n'a encore été recensée, ce qui n'est pas forcément une bonne nouvelle dans ce genre de situations...
4. Cadre légal
4.1 Contraintes légales
[Présentation des contraintes légales s'appliquant à votre application]
En tant que plateforme de partage de contenus audio, Dbox-FM est soumise à plusieurs obligations légales liées à la protection des droits d’auteur. En particulier :
- Le droit d’auteur interdit la mise en ligne de contenus protégés sans autorisation expresse du détenteur des droits (ex. artistes, maisons de disques).
- La responsabilité de l’hébergeur (directive européenne 2000/31/CE) peut être engagée si la plateforme ne réagit pas promptement après signalement d’un contenu illégal.
- La protection des données personnelles (RGPD) s’applique également dès lors que des utilisateurs s’inscrivent et que des données sont collectées.
4.2 Mise en oeuvre de ces contraintes
Afin de respecter ce cadre légal, plusieurs mesures ont été mises en place dans notre projet :
- Accès restreint à la publication : seuls les utilisateurs inscrits peuvent publier des sons.
- Système de signalement : un bouton permet aux utilisateurs de signaler tout contenu soupçonné d’enfreindre les droits d’auteur.
- Modération manuelle : les sons signalés sont examinés par un modérateur, qui peut les supprimer s’ils sont jugés illégaux.
Cependant, il est important de noter que la plateforme ne dispose pas (encore) d’un système automatique de détection de contenus protégés (comme le Content ID de YouTube), ce qui limite sa capacité à empêcher la mise en ligne de contenus illicites en amont.
5. Bilan et Limites
Dans ce cadre pédagogique et expérimental, nous estimons avoir mis en place un bon nombre de mesures de sécurité, dont certaines sont nécessaires (HTTPS, contrôles d'accès), et d'autres sont moins primordiales (certificats clients, monitoring), mais nous ont tout de même permis d'en apprendre plus sur la sécurisation d'une application et de son infrastructure.
Globalement, notre site est plutôt sécurisé sur le plan technique, mais cela est dangereux de le penser totalement à l'abri, c'est pourquoi nous envisageons d'effectuer de prochains changement lors d'un cycle de notre intégration continue :
- Validation encore plus poussée des fichiers entrés par les utilisateurs
- Chiffrement HTTPS du trafic circulant dans le VPN
- Amélioration du monitoring pour détecter des tentatives d'intrusion, envoyer des alertes aux responsables, et éventuellement procéder à un ban d'IP automatique
Le cadre légal est respecté à notre petite échelle, néanmoins, il nous serait amplement nécessaire d'implémenter des mécanismes automatisés à ces fins dans l'éventualité de passage à une échelle plus importante de l'application.