En ce qui concerne de nombreuses réponses utiles, j'espère ajouter de la valeur à ce fil.
L'injection SQL est une attaque qui peut être effectuée via des entrées utilisateur (entrées remplies par un utilisateur, puis utilisées dans des requêtes). Les modèles d'injection SQL sont une syntaxe de requête correcte alors que nous pouvons l'appeler: mauvaises requêtes pour de mauvaises raisons, et nous supposons qu'une mauvaise personne peut essayer d'obtenir des informations secrètes (en contournant le contrôle d'accès) qui affectent les trois principes de sécurité (confidentialité , intégrité et disponibilité).
Maintenant, notre objectif est de prévenir les menaces de sécurité telles que les attaques par injection SQL, la question demandant (comment empêcher une attaque par injection SQL en utilisant PHP), être plus réaliste, le filtrage ou la suppression des données d'entrée est le cas lors de l'utilisation de données d'entrée utilisateur à l'intérieur une telle requête, en utilisant PHP ou tout autre langage de programmation n'est pas le cas, ou comme recommandé par plus de gens pour utiliser une technologie moderne comme une instruction préparée ou tout autre outil prenant actuellement en charge la prévention des injections SQL, considérez-vous que ces outils ne sont plus disponibles? Comment sécurisez-vous votre application?
Mon approche contre l'injection SQL est la suivante: effacer les données entrées par l'utilisateur avant de les envoyer à la base de données (avant de les utiliser dans une requête).
Filtrage des données pour (conversion de données non sécurisées en données sécurisées)
Considérez que PDO et MySQLi ne sont pas disponibles. Comment sécuriser votre application? Me forcez-vous à les utiliser? Qu'en est-il des autres langages autres que PHP? Je préfère fournir des idées générales car elles peuvent être utilisées pour une frontière plus large, pas seulement pour une langue spécifique.
- Utilisateur SQL (limitation des privilèges utilisateur): les opérations SQL les plus courantes sont (SELECT, UPDATE, INSERT), alors, pourquoi accorder le privilège UPDATE à un utilisateur qui n'en a pas besoin? Par exemple, les pages de connexion et de recherche utilisent uniquement SELECT, alors pourquoi utiliser les utilisateurs de base de données dans ces pages avec des privilèges élevés?
RÈGLE: ne créez pas un utilisateur de base de données pour tous les privilèges. Pour toutes les opérations SQL, vous pouvez créer votre schéma comme (deluser, selectuser, updateuser) en tant que noms d'utilisateur pour une utilisation facile.
Voir principe du moindre privilège .
Filtrage des données: avant de créer une entrée utilisateur de requête, elle doit être validée et filtrée. Pour les programmeurs, il est important de définir certaines propriétés pour chaque variable entrée par l'utilisateur:
type de données, modèle de données et longueur des données . Un champ qui est un nombre entre (x et y) doit être exactement validé en utilisant la règle exacte, et pour un champ qui est une chaîne (texte): le modèle est le cas, par exemple, un nom d'utilisateur ne doit contenir que quelques caractères, disons dites [a-zA-Z0-9_-.]. La longueur varie entre (x et n) où x et n (entiers, x <= n).
Règle: la création de filtres exacts et de règles de validation sont les meilleures pratiques pour moi.
Utilisez d'autres outils: ici, je conviendrai également avec vous qu'une instruction préparée (requête paramétrée) et des procédures stockées. Les inconvénients ici sont que ces méthodes nécessitent des compétences avancées qui n'existent pas pour la plupart des utilisateurs. L'idée de base ici est de faire la distinction entre la requête SQL et les données utilisées à l'intérieur. Les deux approches peuvent être utilisées même avec des données non sécurisées, car les données saisies par l'utilisateur ici n'ajoutent rien à la requête d'origine, comme (any ou x = x).
Pour plus d'informations, veuillez lire le cheat sheet OWASP SQL Injection Prevention .
Maintenant, si vous êtes un utilisateur avancé, commencez à utiliser cette défense comme vous le souhaitez, mais, pour les débutants, s'ils ne peuvent pas rapidement mettre en œuvre une procédure stockée et préparer l'instruction, il est préférable de filtrer autant que possible les données d'entrée.
Enfin, considérons qu'un utilisateur envoie ce texte ci-dessous au lieu de saisir son nom d'utilisateur:
[1] UNION SELECT IF(SUBSTRING(Password,1,1)='2',BENCHMARK(100000,SHA1(1)),0) User,Password FROM mysql.user WHERE User = 'root'
Cette entrée peut être vérifiée tôt sans instruction préparée ni procédures stockées, mais pour être sûr, leur utilisation commence après le filtrage et la validation des données utilisateur.
Le dernier point est la détection d'un comportement inattendu qui nécessite plus d'efforts et de complexité; ce n'est pas recommandé pour les applications Web normales.
Un comportement inattendu dans l'entrée utilisateur ci-dessus est SELECT, UNION, IF, SUBSTRING, BENCHMARK, SHA et root. Une fois ces mots détectés, vous pouvez éviter la saisie.
MISE À JOUR 1:
Un utilisateur a commenté que ce post est inutile, OK! Voici ce que OWASP.ORG a fourni :
Défenses principales:
Option # 1: Utilisation d'instructions préparées (Requêtes paramétrées)
Option # 2: Utilisation de procédures stockées
Option # 3: Échapper à toutes les entrées fournies par l'utilisateur
Défenses supplémentaires:
Appliquer également: Moins de privilèges
Effectuer également: Validation des entrées de la liste blanche
Comme vous le savez peut-être, la revendication d'un article doit être appuyée par un argument valide, au moins par une référence! Sinon, c'est considéré comme une attaque et une mauvaise réclamation!
Mise à jour 2:
Depuis le manuel PHP, PHP: Instructions préparées - Manuel :
Échappement et injection SQL
Les variables liées seront échappées automatiquement par le serveur. Le serveur insère leurs valeurs d'échappement aux endroits appropriés dans le modèle d'instruction avant l'exécution. Un indice doit être fourni au serveur pour le type de variable liée, afin de créer une conversion appropriée. Voir la fonction mysqli_stmt_bind_param () pour plus d'informations.
L'échappement automatique de valeurs au sein du serveur est parfois considéré comme une fonction de sécurité pour empêcher l'injection SQL. Le même degré de sécurité peut être atteint avec des instructions non préparées si les valeurs d'entrée sont correctement échappées.
Mise à jour 3:
J'ai créé des cas de test pour savoir comment PDO et MySQLi envoient la requête au serveur MySQL lors de l'utilisation d'une instruction préparée:
AOP:
$user = "''1''"; // Malicious keyword
$sql = 'SELECT * FROM awa_user WHERE userame =:username';
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':username' => $user));
Journal des requêtes:
189 Query SELECT * FROM awa_user WHERE userame ='\'\'1\'\''
189 Quit
MySQLi:
$stmt = $mysqli->prepare("SELECT * FROM awa_user WHERE username =?")) {
$stmt->bind_param("s", $user);
$user = "''1''";
$stmt->execute();
Journal des requêtes:
188 Prepare SELECT * FROM awa_user WHERE username =?
188 Execute SELECT * FROM awa_user WHERE username ='\'\'1\'\''
188 Quit
Il est clair qu'une instruction préparée échappe également aux données, rien d'autre.
Comme mentionné également dans la déclaration ci-dessus,
L'échappement automatique de valeurs au sein du serveur est parfois considéré comme une fonction de sécurité pour empêcher l'injection SQL. Le même degré de sécurité peut être atteint avec des instructions non préparées, si les valeurs d'entrée sont correctement échappées
Par conséquent, cela prouve que la validation des données telle que intval()
c'est une bonne idée pour les valeurs entières avant d'envoyer une requête. De plus, empêcher les données utilisateur malveillantes avant d'envoyer la requête est une approche correcte et valide .
Veuillez consulter cette question pour plus de détails: PDO envoie une requête brute à MySQL tandis que Mysqli envoie une requête préparée, les deux produisent le même résultat
Références:
- Aide-mémoire pour l'injection SQL
- Injection SQL
- Sécurité de l'information
- Principes de sécurité
- La validation des données