Bonjour à tous. Dans cette vidéo, nous allons maintenant aborder la notion d'injection de code. Il s'agit de faire interpréter une chaîne de caractères ou tout autre type de données comme du code afin de le faire exécuter. On peut injecter du code de différents langages, tel que du bash ou du SQL. Pour cette vidéo, nous allons nous concentrer sur la notion d'injection SQL qui consister à injecter dans une requête SGBD du code SQL non prévu à l'aide d'une saisie web. Le principe est de modifier une requête SQL dans le but de contourner l'authentification d'un site, de voler des informations, etc. Il s'agit d'injecter du code SQL dans le contenu d'une requête depuis le champ d'un formulaire de saisie de données. Celui-ci est renseigné par l'utilisateur, que nous qualifierons donc ici également d'attaquant. Reprenons l'exemple de l'architecture précédente. L'attaquant saisit du code SQL dans le formulaire et le valide. Le navigateur, ou alors un programme aveugle, envoie une requête contenant les informations saisies vers le serveur web. Le serveur web transfère la demande au serveur applicatif. Le serveur applicatif génère une requête SQL afin de récupérer les informations nécessaires et la transmet au SGBD. C'est donc ici que l'injection va jouer. Le serveur de base de données retourne le résultat de la requête au serveur applicatif. Le serveur applicatif transmet les informations nécessaires au serveur web. Le serveur web transmet les pages HTML au navigateur client. [AUDIO_VIDE] Prenons un exemple de contournement d'authentification sur un site Internet vulnérable. Le formulaire avec lequel l'attaquant va interagir est le suivant. Le formulaire comporte un champ Login et un champ Password. Il possède aussi un bouton de soumission. Regardons de plus près le code HTML correspondant. Celui-ci est le suivant. Nous pouvons voir que le code associé comporte bien les champs Login et Password, mais aussi que la page PHP appelée lors de la soumission du formulaire est nommée verif.php. Lorsque l'attaquant va soumettre le formulaire, une requête HTTP va être envoyée au serveur qui va la transmettre au serveur Apache. Cette requête contient les informations saisies par l'attaquant dans le formulaire. Regardons la requête HTTP. Comme nous pouvons le voir, la page verif.php est appelée et les paramètres passés à cette page le sont à l'aide de la méthode POST. Ces paramètres sont le Login et le Password qui sont égaux respectivement à User et Password. Lorsque l'on regarde le fichier verif.php, nous pouvons voir que le serveur Apache va se connecter au serveur MySQL, et plus particulièrement à la base de données nommée MOOC. Ensuite, le module PHP du serveur Apache va construire la requête SQL qui sera envoyée au SGBD, et interprêtée par ce dernier comme une requête. Dans notre exemple, c'est le module PHP de la page qui va construire la requête SQL en remplaçant les variables .$login." et ".$mdp. par les valeurs saisies par l'attaquant. Ensuite, il envoie la requête au SGBD MySQL pour que ce dernier l'interprête. C'est ici que va se produire l'injection. Le SGBD va interprêter la requête et retourner le résultat au serveur Apache, qui va ensuite le traiter dans les lignes suivantes. Ce résultat, rendu possible par comparaison du couple de valeurs saisies dans le formulaire, avec un enregistrement de la base de connées, comprend l'identifiant de l'utilisateur, son nom et son prénom. Ce résultat offre, pour la suite, l'accès à ces informations. Il faut noter que, dans le cas d'un fonctionnement normal, si un résultat est retourné, c'est donc que le couple de valeurs fournies login/password existe. Nous pouvons voir ci-dessous que l'utilisateur sera authentifié sur tout le site à l'aide de la variable de sessions $_SESSION['reussi']. L'attaquant, voulant réaliser une injection SQL, va essayer de modifier le comportement de la requête SQL pour que, bien que le couple identifiant/mot de passe ne corresponde pas, il soit identifié sur le site internet. Examinons le code. Les informations saisies, présentes dans la variable $login, peuvent être quelconques, car elles ne sont pas vérifiées. Elles sont donc utilisées telles quelles. L'attaquant peut donc injecter du code SQL dans le formulaire HTML là où il ne devrait entrer qu'un login et un mot de passe. Comment le SGBD rend-il cela possible? Examinons de plus près la chaîne de caractères suivante. Elle sera modifiée en requête à la base de données par le module PHP de Apache. En SQL, le SGBD retourne un résultat si la clause Where est valide. C'est-à -dire qu'un enregistrement dans la base de données contient bien les valeurs de sélection, ici, un couple de valeurs Login et mot de passe. Les deux valeurs doivent exister dans le même enregistrement. Prenons un couple de valeurs au hasard, par exemple login égal pau et pass égal 123. Cela donne la requête suivante : select id,name, firstname from users where login égal paul and pass égal 123. S'il y a un enregistrement dans la base de données où login égal paul et pass égal 123, la clause Where est valide. Alors, le SGBD retournera un résultat au serveur Apache. Le but de l'attaquant va être de faire retourner vraie la requête SQL en injectant du code SQL dans la variable Login ou dans la variable mot de passe. Pour que la clause Where retourne toujours vraie, même en cas de mauvais couple login/mdp, nous allons injecter du code SQL dans la variable mot de passe. Comme vous le savez peut-être, il existe différents opérateurs en SQL tels que Union, Intersect, OR. Nous allons donc nous servir de ces connaissances pour modifier le comportement de la requête. On veut obtenir quelque chose vrai/faux ou vrai. Donc, dans la clause Where, que le couple login/mot de passe soit vrai ou faux, ou alors qu'une deuxième condition soit vraie. On sait par exemple que un égal un est toujours vrai. De même on sait que caractère un égal caractère un est toujours vrai. Il existe d'autres conditions qui peuvent toujours retourner vraies. Si on reprend la requête précédente, nous avons select id,name, firstname from users where login="login saisi" and mot de passe="mot de passe saisi" ou une condition toujours vraie. Pour la condition toujours vraie, prenons caractère un égal caractère un. La requête SQL sera donc, avec les informations saisies par l'attaquant en rouge : select id, name, firstname from users where login = "une chaîne" and pass = "un mot de passe" ou "1 = 1". Comme vous pouvez le voir, la saisie doit respecter la syntaxe SQL. C'est pour cela que nous mettons guillemet fermant avant le "or". Vous pouvez aussi remarquer que nous n'ajoutons pas de guillemet à la fin de notre injection car il est déjà présent dans le code PHP de la requête. Avec la partie en rouge saisie par l'attaquant, la requête SQL sera interprêtée comme ceci : entre parenthèses, login = "une chaîne" and pass = "un mot de passe", on ferme la parenthèse, "ou 1 = 1". En SQL, l'opérateur "and" est prioritaire sur l'opérateur "or". Donc le SGBD va d'abord évaluer le morceau suivant de la requête : "login = une chaîne et pass = un mot de passe". retourner les enregistrements correspondants dans la base de données. Si la condition est fausse, alors il n'y a aucun enregistrement à retourner pour cette partie de la requête. Mais il va ensuite évaluer la condition suivante : "ou 1=1". Cette condition étant toujours vraie, le caractère "un" étant toujours égal au caractère "un", alors tous les enregistrements de la base de données seront retournés. Regardons de nouveau notre code. Le code exécuté vérifie qu'un résultat a été retourné. Dans notre cas, toute la table des comptes utilisateurs a été retournée. Par conception, PHP prendra en compte le premier enregistrement, c'est-à -dire que pour le serveur, l'utilisateur authentifié est celui du premier enregistrement de la table. A noter que si le premier utilisateur dans la table est l'administrateur, alors l'attaquant aura les droits d'administration sur le site. C'est pourquoi une bonne pratique de sécurisation est que l'administrateur se supprime de la base lorsque le site est en production. Nous venons de voir une injection SQL très simple, mais ne sous-estimez pas les attaquants en pensant que pour sécuriser votre formulaire, il suffit de mettre en place un filtrage de la saisie du login par des règles de formation des noms propres avant d'interroger le SGBD. Il existe en effet des injections SQL plus poussées. Celles-ci peuvent fonctionner ailleurs, à d'autre endroits, si les entrées "utilisateur" ne sont pas contrôlées systématiquement. Il est aussi par exemple possible d'injecter du code directement dans l'URL du site web. La capacité qu'a un attaquant à contourner un système d'authentification, voler des informations, n'est limitée que par son savoir et son imagination. Il ne faut jamais faire confiance aux données saisies par un utilisateur. J'insiste : vous devez contrôler toutes les saisies "utilisateur". C'est ce que nous allons voir dans la prochaine vidéo.