1. Preface
Ce document présente un retour d’expérience d’une introduction à la cybersécurité, d’après le bloc 3 du référentiel du BTS SIO SLAM.
Dans le cadre de leur formation (troisième semestre), les étudiants ont eu la charge de réaliser une application web, en mode projet. Outre le fait que leur projet devait être livré à une date donnée (sur un dépôt git distant de leur choix), associé à un rapport détaillé (README du projet), nous attendions qu’il intègre des scénarios d’actions mal intentionnées et la mise en oeuvre de contre mesures de défense.
Les exemples de Evil User Stories ([EvilUS]) présentés ici, sont tirés de travaux de ces étudiants (deuxième année du BTS SLAM, lycée Léonard de Vinci de Melun, 2021-2022). Ces exemples sont donc centrés sur des problèmes liés aux cas d’utilisation métier de ce projet.
Pour ceux qui souhaitent reconduire cette expérience très exactement, voici le lien vers le projet : https://ocapuozzo.github.io/mission-etl-csv/ (libre utilisation). Compter minimum 3 semaines de travail étudiant, couvrant toutes les plages de TP info, plus un temps certain de travail à domicile (première semaine des vacances de Toussaint, par exemple)
2. Résumé
La cybersécurité en développement logiciel (défense) nécessite un esprit d’analyse certain qui s’appuie en partie sur une connaissance fine des technologies mises en oeuvre (infrastructures, protocoles, architectures des tiers, architectures en couches…). Cette connaissance se forge par l’expérience.
Enseigner la cybersécurité à BAC+2, à des débutants, c’est accompagner l'étudiant sur le chemin de l’expérience et en même temps l'éclairer à la fois sur les bonnes pratiques et les usages déviants.
Pour autant, l'étudiant a tendance à se focaliser principalement sur la consolidation de connaissances techniques nouvelles (comprendre la technologie, mettre au point l’application) laissant une moindre place à l'étude de bonnes pratiques et des usages mal intentionnés. Normal, car ces études ont comme prérequis une bonne dose d’expérience…
L'étude des risques cyber, tout comme celle des tests unitaires, est discriminante dans la mesure où elle induit un travail et un recul sur un réel construit et opérationnel (l’application).
L’accès à ce type de formation est ainsi clairement monté en exigence, et va dans le sens des attendus de professionnels du secteur. (https://www.lemonde.fr/blog/binaire/2015/11/05/la-culture-de-la-cybersecurite/).
À nous, enseignants, de relever le défi de sensibiliser l’ensemble de nos étudiants aux risques liés à la cybersécurité, et aux actions pour en minimiser l’impact.
3. Une sélection d’Evil User Stories proposés par les étudiants
3.1. Team : Le nain et l'échelle
Concept de contre-mesure : [moindre-privilege], [reduction-de-la-surface-d-attaque]
Contre-mesure : En tant que développeur, je vais créer un identifiant de base de données spécialement pour la base de données de Vetux-Line pour empêcher un utilisateur malveillant d’accéder à d’autres bases de données sur le même serveur.
Pour cela avec phpMyAdmin
je crée ce nouvel utilisateur comme ceci:
Et dans le fichier .env
je précise les informations de connexion à la base de données avec cette ligne:
DATABASE_URL="mysql://vetux_line:wNgEf23m*7MZdWZ9@127.0.0.1:3306/vetux_line?serverVersion=mariadb-10.4.21"
Mise en garde de l’enseignant
L’utilisation de solutions d’administration de base de données par l’intermédiaire d’un tiers applicatif comme Préférez une console d’administration, connexion en |
Concept de contre-mesure : [moindre-privilege]
Contre-mesure: En tant que développeur, je veux restreindre l’accès à certaines pages à des utilisateurs ayant un rôle spécifique, afin d'éviter qu’un utilisateur malveillant ait accès aux actions et données de ces rôles. Pour cela je configure dans le fichier security.yaml
les lignes de acces_control
:
access_control: - { path: ^/utilisateur, roles: ROLE_GESTIONNAIRE } - { path: ^/utilisateur/admin, roles: ROLE_ADMIN } - { path: ^/home, roles: ROLE_GESTIONNAIRE }
Ainsi, toutes les routes commençant par /utilisateur/admin
seront uniquemant accessibles par les utilisateurs avec le rôle ROLE_ADMIN
et de même pour les routes commençant par /home
pour les utilisateurs avec le rôle ROLE_GESTIONNAIRE
.
Dans les contrôleurs de l’application, je définie un préfixe de route pour toutes ses méthodes contrôleur. Par exemple dans UtilisateurController.php
j’utilise une annotation pour définir la racine de route utilisateur
, propre à cette classe et valable pour toutes ses méthodes contrôleur :
#[Route('/utilisateur')]
class UtilisateurController extends AbstractController
Ainsi les méthodes contrôleur de cette classe ayant une route commençant par /admin
, ne seront accessibles qu’aux utilisateurs ayant le rôle ROLE_ADMIN
.
La classe UploadController.php
aura /home
comme préfixe de route.
#[Route('/home')]
class UploadController extends AbstractController
Ainsi, toutes ses méthodes contrôleur seront accessibles qu’aux seuls utilisateurs ayant le ROLE_GESTIONNAIRE
.
Concepts de contre-mesure : ne pas diffuser de données techniques d’erreur, ne jamais faire confiance aux données d’entrée.
Contre-mesure : En tant que développeur, je veux seulement autoriser les fichiers csv
dans l’upload pour éviter des attaques malveillantes. Pour cela j’interviens dans la classe contrôleur UploadController.php
afin de vérifier le type de chaque fichier reçu :
foreach ($files as $file) {
$filetype = $file->getMimeType();
if (str_contains($filetype, '/csv')){
$filename = $file->getClientOriginalName();
$uploader->moveTo($uploadDir, $file, $filename);
} else {
return $this->render('home/index.html.twig');
}
}
getMimeType()
renvoie le type de fichier avec son extension sous forme: type/extension
.
Ici on vérifie juste si dans cette réception on a bien l’extension csv
via un appel à str_contains
et si oui on récupère le nom du fichier et on le traite (avec notre objet service référencé par $uploader
), sinon on renvoie à la page d’upload.
Nos fichiers csv
ont comme MimeType application/csv
et pas text/csv
, on a donc dû vérifier seulement la présence de l’extension.
Remarque enseignant
Attention, solution naïve, l’habit ne fait pas le moine ! L’extension informe sur le contenu d’un fichier mais ne le garantit pas. Constatez-le par vous-même : Le changement d’extension du nom d’un fichier est sans impact sur son contenu. D’autre part, la limite de la taille maximale des fichiers autorisés est également à considérer. Généralement sous la forme d’un paramètre du service HTTP en amont. |
3.2. Team : Les Pas d’ID
Concept de contre-mesure : Menaces [DDoS] à intégrer dans le plan de mise en production.
Contre-mesure : En tant que développeur pour empêcher les attaques dos je m’assure que l’application n’utilise pas de composants sujets à de telles attaques et je me sers des protections mises a disposition par les hébergeurs (mécanisme de filtrage en bordure de réseau par exemple)
Exemple hébergeur OVH (présenté par l’enseignant)
Ci-dessous, des extraits de courrier envoyé par OVH à un de ses clients suite à la détectection une attaque [DDoS]. Message de l’hébergeur OVH ayant détecté une attaque DDoS
Madame, Monsieur, Nous venons de détecter une attaque sur l'adresse IP x.x.x.x. Afin de protéger votre infrastructure, nous avons aspiré votre traffic sur notre infrastructure de mitigation. Toute l'attaque sera ainsi filtrée par notre infrastructure, et seul le traffic légitime arrivera jusqu'à vos serveurs. A la fin de l'attaque, votre infrastructure sera immédiatement retirée de la mitigation. Puis, quelque temps plus tard : Message de l’hébergeur OVH ayant détecté la fin de l’attaque
Madame, Monsieur, Nous ne détectons actuellement plus d'attaque sur l'adresse IP x.x.x.x. Votre infrastructure est maintenant retirée de notre mitigation. Pour plus d'informations sur l'infrastructure de mitigation OVH : https://www.ovh.com/fr/anti-ddos/ Cordialement, Votre Service client OVHcloud |
3.3. Team : Yannick
Concept de contre-mesure : [moindre-privilege]
Contre-mesure : En tant que développeur, afin d’empêcher les personnes malveillantes qui souhaitent, à partir de la barre d’adresse, accéder aux différentes routes de l’application Vetux-Line sans être connecté.
Les méthodes contrôleur de la classe IndexController
sont annotées par @IsGranted("ROLE_ADMIN")
. Cette annotation permet de restreindre l’accès à tous les utilisateurs qui ne sont pas connecté ou qui ne possède pas le rôle ROLE_ADMIN
aux différentes routes du controller. La personne malveillante, en essayant de se connecter à la route admin/fusion par exemple, ne va pas pouvoir y accéder, car elle sera directement redirigée sur la page de connexion.
Vidéo de démonstration : https://youtu.be/DO1L1NVX6XI
Ramarque
Avec
|
3.4. Team : Schoolalexis
Concept de contre-mesure : [reduction-de-la-surface-d-attaque]
Contre-mesure : En tant que développeur, afin d’empêcher des personnes malveillantes qui souhaitent, à partir de la base de données, se connecter aux comptes des utilisateurs et exploiter leurs mots de passe (dans le cas de l’application Vetux Line), je sécurise le fichier .env
qui contient l’identifiant de connexion à la base de données.
Pour cela, je n’inscris pas de données sensibles dans .env
(données de production), et je crée un fichier .env.local
pour y placer des données en lien avec l’environnement de test (machine du dev par exemple). Je m’assure que ce fichier n’est pas pris en compte dans le logiciel de versionnage Git
, pour ne pas être sauvegardé sur un serveur distant.
Exemple :
# symfony/framework-bundle #
/.env.local
/.env.local.php
/.env.*.local
/config/secrets/prod/prod.decrypt.private.php
/public/bundles/
/var/
/vendor/
# symfony/framework-bundle #
Dans .env
j’inscris :
DATABASE_URL="mysql://<user>:<password>@127.0.0.1:3306/<database>?serverVersion=<version>"
À charge de la personne responsable de la mise en production de renseigner les données de connexion à la base de données dans le fichier de configuration .env
.
Remarque enseignant
Une autre solution consiste à chiffrer les variables d’environnement.
— https://symfony.com/doc/current/configuration.html#configuration-based-on-environment-variables
Symfony |
3.5. Team : Les Alternants
Concept de contre-mesure : [maintien-en-conditions-de-securite]
Contre-mesure : En tant que développeur je surveille les mises à jour de Symfony, particulièrement en terme de sécurité (site https://symfony.com/
), ainsi que les autres composants tiers utilisés par mon projet. Exemple de commandes :
symfony self:update
puis
composer update
Je réalise cette commande supplémentaire pour vérifier qu’il n’y a pas d’autres failles de sécurité en exécutant cette commande :
symfony security:check
Pour vérifier que les composants dont dépend l’application n’ont pas de failles détectées à ce jour. Si nécessaire je mets à jour la version des composants en prenant soin de bien consulter les recommandations de mises à niveau et de tester l’application (tests de non régression)
Concept de contre-mesure : [reduction-de-la-surface-d-attaque]
Justification: En effet, plusieurs études (https://www.cyclonis.com/fr/rapport-83-pour-cent-utilisateurs-interroges-utilisent-meme-mot-de-passe-plusieurs-sites/ ou https://www.zdnet.fr/actualites/mot-de-passe-1-personne-sur-7-n-en-utilise-qu-un-seul-partout-39829024.htm et bien d’autres..) démontrent que les personnes utilisent souvent le même mot de passe un peu partout.
Contre-mesure : En tant que développeur, si jamais une grosse fuite de données se produit, je sécurise la base de données en chiffrant tous les mots de passe pour éviter de réutiliser les mots de passe des utilisateurs.
J’ai donc haché le mot de passe des utilisateurs par l’intermédiaire du module de sécurité de Symfony, en particulier :
use
Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
[...]
3.6. Team : Tournesol
Concepts de contre-mesure : [defense-en-profondeur], [zero-trust], [moindre-privilege]
Exemple connu Optical Center avril 2019 (utilisateur sans privilège !) : Une délégation de la CNIL a effectué des vérifications en ligne qui ont permis de constater qu’il était possible d’accéder librement, à partir des « URL » qui lui avaient été transmises, à des factures contenant les données à caractère personnel suivantes: le nom, le prénom, l’adresse postale, la correction ophtalmologique et, pour certaines d’entre elles, la date de naissance des clients ainsi que leur numéro d’inscription au répertoire national d’identification des personnes physiques (NIR). La délégation a également constaté qu’il était possible, depuis le domaine « optical-center.fr » et sans authentification préalable dans l’espace client, d’exporter au format « CSV », un échantillon de 2085 fichiers correspondant, après suppression des doublons, aux données de 1207 clients et faisant notamment apparaître 158 NIR. La société Optical Center a eu une amende de 250 000 euros (source : https://www.cnil.fr/sites/default/files/atoms/files/decision-n-422575.pdf)
Contre-mesure : En tant que développeur, je m’assure que les utilisateurs de même privilège n’accèdent pas aux fonctionnalités leur permettant d’agir sur les données personnelles d’autes utilisateurs de même privilège.
/**
* @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_GESTIONNAIRE')")
*
* @Route("/{id}/edit", name="utilisateur_edit", methods={"GET","POST"})
*/
public function edit(Request $request, Utilisateur $utilisateur,
UserPasswordHasherInterface $passwordHasher): Response
{
// code sous garde de sécurité qui manque de "robustesse"
[...]
}
Une solution consiste à affiner, dans le corps de la méthode, l’habilitation de l’utilisateur à solliciter ce service.
/**
* @Security("is_granted('ROLE_ADMIN') or is_granted('ROLE_GESTIONNAIRE')")
*
* @Route("/{id}/edit", name="utilisateur_edit", methods={"GET","POST"})
*/
public function edit(Request $request, Utilisateur $utilisateur,
UserPasswordHasherInterface $passwordHasher,
LoggerInterface $logger): Response
{
$isAdmin = $this->isGranted('ROLE_ADMIN');(1)
if (($this->getUser()->getUserIdentifier() !== $utilisateur->getUserIdentifier())
&& !$isAdmin) { (2)
// un utilisateur ne peut pas modifier/consulter les données
// d'un autre, sauf s'il est ADMIN
$logger->info('This user '. $this->getUser()->getUserIdentifier() (3)
. ' hack attempt edit user id : ' . $utilisateur->->getUserIdentifier());
$this->addFlash("message", "Vous ne pouvez pas modifier cet utilisateur"); (4)
return $this->redirectToRoute('membre'); (5)
}
[...]
1 | Vérifier si l’utilisateur courant est un administrateur |
2 | Seuls l’utilisateur concerné ou les administrateurs sont elligibles ici |
3 | journalise cette action non autorisée (TODO vérifier sa temporalisation) |
4 | Est-il opportun de présenter un message à cet utilisateur ? |
5 | Retourne un ordre de redirection, car cette requête n’a pas lieu d'être. |
Journalisation
On remarquera l’instruction de journalisation (logger) de l’action malveillante. Très utile pour analyser des attaques silencieuses. La généralisation de journalisation de toutes actions illégales est à envisager ([zero-trust]) |
4. Conclusion
Cette première expérimentation (première année d’examen du nouveau référentiel SIO) a permis de mesurer la difficulté à enseigner les principes de cybersécurité à des débutants en programmation. Les propositions d'étudiants présentées ici ont, en partie, été reformulées, mais restent relativement fidèles à leur version originale.
Seule la proposition de la team Tournesol n’est pas une proposition d'étudiant (Evil User Story n°9, gestion des données du profil utilisateur contrôlée uniquement sur le rôle de l’utilisateur). Malgré le fait que le cas Optical Center ait été évoqué en cours, la faiblesse du code généré par le module maker d’authentification dans sa version d’octobre 2021 n’a pas fait l’objet d’une contre-mesure. Nous pensons que cette proposition n’a pas été retenue par les étudiants de par sa relative complexité, qui nécessite un temps de recul basé sur une expérience en devenir.
4.1. Qualité de l’expérience
Il existe de la part de l'étudiant une tendance certaine à rechercher systématiquement une solution à tout problème sur internet. Normal, car on leur a toujours dit que l’on trouve (de) tout sur internet :)), rendant difficile, pour l’apprenant, de distinguer ce qui est du ressort d’une solution logique à construire - avec les moyens sous la main - d’une recherche d’une solution toute faite.
Par exemple le projet demande une fusion sélective très particulière de deux fichiers CSV, et quelques étudiants ne se sont pas contentés d’un exemple de code de lecture/écriture d’un tel fichier, cherchant durant de longs moments une solution de fusion clé en main sur le net… |
Dans la même veine, suivre un tutoriel n’est pas de l’expérience, mais aller au delà, c’est à dire comprendre ce qui a été réalisé, l'adapter à un projet, l'étendre sur la base d’une idée d’amélioration ou créer de nouvelles fonctionnalités, oui. L’expérience forge la créativité et inversement.
La recheche par l'étudiant de scénarios d’usages déviants, et leur contre-mesure, participe au développement de sa créativité. C’est une dimension que nous, professeurs, avons décidé de prendre en compte dans les évaluations.
Enfin, signalons qu’un tiers environ de nos étudiants n’a pas été en mesure de réaliser le travail demandé. Leur capacité à transposer des savoir faire, leur niveau d’implication, n’ont pas été suffisants pour atteindre les objectifs fixés.
Test
5. Glossaire
- Evil User Story
-
Récit d’un utilisateur (User Story) mal intentionné, connu aussi sous le nom abuser story.
- Deni de service
-
Une attaque par déni de service vise à rendre indisponible un ou plusieurs services par surcharge de la bande passante ou épuisement des ressources système. "Certaines attaques visent à épuiser les capacités de traitement d’une cible. Par exemple, un attaquant peut chercher à atteindre la limite du nombre de connexions concurrentes qu’un serveur web peut traiter. Dans ce cas, l’attaquant envoie en permanence un grand nombre de requêtes HTTP GET ou POST au serveur ciblé. Il est également possible d’envoyer des requêtes partielles, puis de transmettre la suite de ces requêtes à intervalles réguliers, dans le but de maintenir les connexions ouvertes le plus longtemps possible et d’éviter la fermeture des connexions au-delà d’un délai fixé. D’autres types d’attaques applicatives cherchent à épuiser les ressources de calcul d’un serveur en initiant un grand nombre de sessions TLS, ou encore à tirer parti de faiblesses dans la conception d’une application web" Source : https://www.ssi.gouv.fr/uploads/2015/03/NP_Guide_DDoS.pdf
- Ligne de commande
-
Une interface en ligne de commande (en anglais command line interface, couramment abrégé
CLI
) est une interface homme-machine dans laquelle la communication entre l’utilisateur et l’ordinateur s’effectue en mode texte. source : https://fr.wikipedia.org/wiki/Interface_en_ligne_de_commande - Mitigation
-
La mitigation concerne les moyens et mesures mis en place pour atténuer les effets négatifs sur un serveur ou un service liés aux attaques DDoS. La mitigation consiste à filtrer le flux pour ne laisser passer que le trafic légitime. source : https://www.ovh.com/fr/anti-ddos/mitigation.xml
- Zero-Trust
-
Le modèle Zero Trust s’inscrit dans la logique de « défense en profondeur » promue historiquement par l’ANSSI, il constitue une modification du paradigme de la stricte logique périmétrique qui a longtemps prévalu. Mise en garde l’ANSSI : https://www.ssi.gouv.fr/agence/publication/le-modele-zero-trust/
- Principe de moinde privilège
-
Ce principe vise à n’octroyer aux éléments et acteurs du système que les permissions strictement nécessaires pour fonctionner, ceci afin de limiter le risque de vol, d’altération ou de destruction de données dans le cas de compromission d’un ou plusieurs éléments. (ANSSI)
- Défense en profondeur
-
Technique qui consite à ne pas laisser une seule couche de sécurité gérer le parfeu de sécurité. En développement logiciel, cela consiste à munir certaines briques logicielles de contrôles suplémentaires de sécurité.
- Réduction de la surface d’attaque
-
L’ensemble des éléments techniques du SI qui peuvent être utilisés pour réaliser une attaque. Une surface d’attaque est d’autant plus large que le nombre d’éléments distincts est grand ou que ces derniers présentent des vulnérabilités exploitables par un attaquant. (ANSSI - recommandation pour la protections des système d’information essentiels)
- Maintien en conditions de sécurité
-
Ensemble des mesures organisationnelles et techniques concourant à maintenir le niveau de sécurité d’un SI tout au long de son cycle de vie. (ANSSI - guide_protection_des_systemes_essentiels)
à compléter…