Injection SQL
Injection SQL
L'injection SQL est une technique d'injection de code qui peut détruire votre base de données.
L'injection SQL est l'une des techniques de piratage Web les plus courantes.
L'injection SQL est le placement de code malveillant dans des instructions SQL, via une entrée de page Web.
SQL dans les pages Web
L'injection SQL se produit généralement lorsque vous demandez à un utilisateur une entrée, comme son nom d'utilisateur/ID utilisateur, et au lieu d'un nom/ID, l'utilisateur vous donne une instruction SQL que vous exécuterez sans le savoir sur votre base de données.
Regardez l'exemple suivant qui crée une
SELECT
instruction en ajoutant une variable (txtUserId) à une chaîne de sélection. La variable est extraite de l'entrée utilisateur (getRequestString) :
Exemple
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Le reste de ce chapitre décrit les dangers potentiels de l'utilisation de l'entrée utilisateur dans les instructions SQL.
L'injection SQL basée sur 1=1 est toujours vraie
Reprenez l'exemple ci-dessus. L'objectif initial du code était de créer une instruction SQL pour sélectionner un utilisateur, avec un identifiant d'utilisateur donné.
Si rien n'empêche un utilisateur d'entrer une "mauvaise" entrée, l'utilisateur peut entrer une entrée "intelligente" comme celle-ci :
Identifiant d'utilisateur:
Ensuite, l'instruction SQL ressemblera à ceci :
SELECT * FROM Users WHERE UserId = 105 OR 1=1;
Le SQL ci-dessus est valide et renverra TOUTES les lignes de la table "Utilisateurs", puisque OR 1=1 est toujours VRAI.
L'exemple ci-dessus vous semble-t-il dangereux ? Que faire si la table "Utilisateurs" contient des noms et des mots de passe ?
L'instruction SQL ci-dessus est sensiblement la même que celle-ci :
SELECT UserId, Name, Password
FROM Users WHERE UserId = 105 or 1=1;
Un pirate peut avoir accès à tous les noms d'utilisateur et mots de passe d'une base de données, en insérant simplement 105 OR 1=1 dans le champ de saisie.
L'injection SQL basée sur ""="" est toujours vraie
Voici un exemple de connexion d'un utilisateur sur un site Web :
Nom d'utilisateur:
Mot de passe:
Exemple
uName = getRequestString("username");
uPass = getRequestString("userpassword");
sql = 'SELECT * FROM Users WHERE Name ="' + uName + '" AND Pass ="' + uPass +
'"'
Résultat
SELECT * FROM Users WHERE Name ="John Doe" AND Pass ="myPass"
Un pirate peut accéder aux noms d'utilisateur et aux mots de passe d'une base de données en insérant simplement " OR ""=" dans la zone de texte du nom d'utilisateur ou du mot de passe :
Nom d'utilisateur:
Mot de passe:
Le code sur le serveur créera une instruction SQL valide comme celle-ci :
Résultat
SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""=""
Le SQL ci-dessus est valide et renverra toutes les lignes de la table "Utilisateurs", puisque OR ""="" est toujours VRAI.
Injection SQL basée sur des instructions SQL par lots
La plupart des bases de données prennent en charge les instructions SQL par lots.
Un lot d'instructions SQL est un groupe de deux ou plusieurs instructions SQL, séparées par des points-virgules.
L'instruction SQL ci-dessous renverra toutes les lignes de la table "Utilisateurs", puis supprimera la table "Fournisseurs".
Exemple
SELECT * FROM Users; DROP TABLE Suppliers
Regardez l'exemple suivant :
Exemple
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = " + txtUserId;
Et l'entrée suivante :
Identifiant d'utilisateur:
L'instruction SQL valide ressemblerait à ceci :
Résultat
SELECT * FROM Users WHERE
UserId = 105; DROP TABLE Suppliers;
Utiliser les paramètres SQL pour la protection
Pour protéger un site Web contre l'injection SQL, vous pouvez utiliser des paramètres SQL.
Les paramètres SQL sont des valeurs qui sont ajoutées à une requête SQL au moment de l'exécution, de manière contrôlée.
Exemple de rasoir ASP.NET
txtUserId = getRequestString("UserId");
txtSQL = "SELECT *
FROM Users WHERE UserId = @0";
db.Execute(txtSQL,txtUserId);
Notez que les paramètres sont représentés dans l'instruction SQL par un marqueur @.
Le moteur SQL vérifie chaque paramètre pour s'assurer qu'il est correct pour sa colonne et qu'il est traité littéralement, et non comme faisant partie du SQL à exécuter.
Un autre exemple
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
db.Execute(txtSQL,txtNam,txtAdd,txtCit);
Exemples
Les exemples suivants montrent comment créer des requêtes paramétrées dans certains langages Web courants.
SÉLECTIONNER L'INSTRUCTION DANS ASP.NET :
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = @0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("@0",txtUserId);
command.ExecuteReader();
INSÉRER DANS LA DÉCLARATION DANS ASP.NET :
txtNam = getRequestString("CustomerName");
txtAdd = getRequestString("Address");
txtCit = getRequestString("City");
txtSQL = "INSERT INTO Customers (CustomerName,Address,City) Values(@0,@1,@2)";
command = new SqlCommand(txtSQL);
command.Parameters.AddWithValue("@0",txtNam);
command.Parameters.AddWithValue("@1",txtAdd);
command.Parameters.AddWithValue("@2",txtCit);
command.ExecuteNonQuery();
INSÉRER DANS LA DÉCLARATION EN PHP :
$stmt = $dbh->prepare("INSERT INTO Customers (CustomerName,Address,City)
VALUES (:nam, :add, :cit)");
$stmt->bindParam(':nam', $txtNam);
$stmt->bindParam(':add', $txtAdd);
$stmt->bindParam(':cit', $txtCit);
$stmt->execute();