Tout savoir sur l'injection SQL en PHP - comment se protéger des attaques
L'injection SQL est une technique d'attaque qui vise à exploiter les vulnérabilités dans une application web pour accéder à sa base de données. Les attaquants peuvent utiliser cette technique pour récupérer des informations sensibles, telles que des noms d'utilisateur et des mots de passe, ou pour modifier, ajouter ou supprimer des données dans la base de données. Les applications web vulnérables à l'injection SQL peuvent être compromises de manière significative, ce qui peut entraîner des pertes financières, des violations de données et des dommages à la réputation de l'entreprise.
Il est important de prendre des mesures pour se protéger contre les injections SQL, telles que la validation et l'assainissement des données d'entrée dans les applications web. En outre, il est important de garder à jour les applications et les serveurs pour s'assurer que les correctifs de sécurité sont appliqués et que les vulnérabilités sont corrigées dès qu'elles sont découvertes.
Exemple
Supposons que vous ayez une table d'utilisateurs nommée users avec les colonnes id
, nom
, email
et motdepasse
. Vous pouvez créer une fonction qui utilise une requête préparée pour sélectionner un utilisateur en fonction de son nom d'utilisateur et de son mot de passe:
function selectUser($username, $password) {
$conn = new PDO("mysql:host=localhost;dbname=mydatabase", "username", "password");
$stmt = $conn->query("SELECT * FROM users WHERE nom = ".$username." AND motdepasse = ".$password);
$rows = $stm->fetchAll();
return $rows[0];
}
Ce code PHP effectue une requête SQL pour récupérer les informations d'un utilisateur en utilisant son nom d'utilisateur et son mot de passe. Cependant, le code présente une vulnérabilité de sécurité importante car il est sujet aux attaques d'injection SQL.
Plus précisément, la fonction selectUser se connecte à une base de données MySQL à l'aide de l'interface de programmation PDO. Elle prend deux paramètres d'entrée : $username
qui représente le nom d'utilisateur et $password
qui représente le mot de passe. Ensuite, elle exécute une requête SQL pour récupérer toutes les informations de l'utilisateur dont le nom d'utilisateur correspond à la variable $username
et le mot de passe correspond à la variable $password
. Cependant, la requête SQL est mal construite car elle concatène simplement les variables $username
et $password
dans la chaîne de la requête SQL, ce qui la rend vulnérable aux attaques d'injection SQL.
En général, les attaquants cherchent à utiliser des caractères spéciaux ou des instructions SQL pour compromettre la requête et accéder aux données qu'ils ne devraient pas être en mesure de voir, tels que des informations d'identification d'utilisateurs ou des informations de carte de crédit.
Par exemple, supposons que l'utilisateur avec le nom "admin"
existe dans la table des utilisateurs. Si un attaquant utilise la valeur admin';--
pour la variable $username
et une valeur quelconque pour la variable $password
, cela pourrait permettre à l'attaquant de contourner l'authentification et d'accéder aux informations de l'utilisateur "admin"
. Cela se produit parce que l'attaque utilise un caractère de guillemet simple (')
pour fermer la chaîne de caractères de la requête SQL, puis ajoute deux tirets (--)
pour ignorer tout ce qui suit et annuler la partie de la requête SQL qui vérifie le mot de passe.
Pour corriger cette vulnérabilité, il est important d'utiliser des requêtes préparées PDO, qui permettent de séparer les paramètres de la requête SQL de la chaîne de la requête. Le code modifié devrait ressembler à ceci :
function selectUser($username, $password) {
$conn = new PDO("mysql:host=localhost;dbname=mydatabase", "username", "password");
$stmt = $conn->prepare("SELECT * FROM users WHERE nom = :username AND motdepasse = :password");
$stmt->bindParam(':username', $username);
$stmt->bindParam(':password', $password);
$stmt->execute();
$rows = $stmt->fetchAll();
return $rows[0];
}
Dans ce code, les paramètres :username
et :password
sont définis dans la requête préparée avec les deux points. Ensuite, les paramètres sont liés aux variables $username
et $password
à l'aide de la méthode bindParam()
. Enfin, la requête est exécutée en appelant la méthode execute().
Avec cette modification, le code est beaucoup plus sûr et résistant aux attaques d'injection SQL.