une - Comment puis-je empêcher l'injection SQL en PHP?




php sql injection protection function (19)

Si l'entrée utilisateur est insérée sans modification dans une requête SQL, l'application devient vulnérable à l' injection SQL , comme dans l'exemple suivant:

$unsafe_variable = $_POST['user_input']; 

mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");

C'est parce que l'utilisateur peut entrer quelque chose comme value'); DROP TABLE table;-- value'); DROP TABLE table;-- et la requête devient:

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

Que peut-on faire pour empêcher cela?


Avertissement de sécurité : Cette réponse n'est pas conforme aux meilleures pratiques de sécurité. Échapper est inadéquat pour empêcher l'injection SQL , utilisez plutôt des instructions préparées . Utilisez la stratégie décrite ci-dessous à vos risques et périls. (En outre, mysql_real_escape_string() été supprimé de PHP 7.)

Vous pouvez faire quelque chose de fondamental comme ceci:

$safe_variable = mysql_real_escape_string($_POST["user-input"]);
mysql_query("INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

Cela ne résoudra pas tous les problèmes, mais c’est un très bon tremplin. J'ai omis des éléments évidents tels que la vérification de l'existence de la variable, son format (nombres, lettres, etc.).


Avertissement: l'exemple de code de cette réponse (comme l'exemple de code de la question) utilise l'extension mysql de PHP, obsolète en PHP 5.5.0 et entièrement supprimée en PHP 7.0.0.

Si vous utilisez une version récente de PHP, l'option mysql_real_escape_string décrite ci-dessous ne sera plus disponible (bien que mysqli::escape_string soit un équivalent moderne). De nos jours, l'option mysql_real_escape_string n'aurait de sens que pour le code hérité d'une ancienne version de PHP.

Vous avez deux options: échapper les caractères spéciaux dans votre unsafe_variable , ou utiliser une requête paramétrée. Les deux vous protégeraient de l'injection SQL. La requête paramétrée est considérée comme la meilleure pratique, mais il faudra passer à une nouvelle extension mysql en PHP avant de pouvoir l'utiliser.

Nous couvrirons la chaîne à impact inférieur échappant en premier.

//Connect

$unsafe_variable = $_POST["user-input"];
$safe_variable = mysql_real_escape_string($unsafe_variable);

mysql_query("INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

//Disconnect

Voir aussi les détails de la fonction mysql_real_escape_string .

Pour utiliser la requête paramétrée, vous devez utiliser MySQLi plutôt que les fonctions MySQL . Pour réécrire votre exemple, nous aurions besoin de quelque chose comme ce qui suit.

<?php
    $mysqli = new mysqli("server", "username", "password", "database_name");

    // TODO - Check that connection was successful.

    $unsafe_variable = $_POST["user-input"];

    $stmt = $mysqli->prepare("INSERT INTO table (column) VALUES (?)");

    // TODO check that $stmt creation succeeded

    // "s" means the database expects a string
    $stmt->bind_param("s", $unsafe_variable);

    $stmt->execute();

    $stmt->close();

    $mysqli->close();
?>

La fonction clé que vous voudrez lire ici est mysqli::prepare .

En outre, comme d'autres l'ont suggéré, il peut être utile / plus facile d'intensifier une couche d'abstraction avec quelque chose comme PDO .

Veuillez noter que le cas sur lequel vous avez posé des questions est assez simple et que des cas plus complexes peuvent nécessiter des approches plus complexes. En particulier:

  • Si vous souhaitez modifier la structure du mysql_real_escape_string SQL en fonction des entrées de l'utilisateur, les requêtes paramétrées ne vont pas vous aider et l'échappement requis n'est pas couvert par mysql_real_escape_string . Dans ce type de cas, il serait préférable de passer l'entrée de l'utilisateur dans une liste blanche pour s'assurer que seules les valeurs "sûres" sont autorisées.
  • Si vous utilisez des entiers provenant d'une entrée utilisateur dans une condition et que vous mysql_real_escape_string approche mysql_real_escape_string , vous souffrirez du problème décrit par Polynomial dans les commentaires ci-dessous. Ce cas est plus complexe car les entiers ne seraient pas entourés de guillemets. Vous pouvez donc régler le problème en validant que la saisie de l'utilisateur ne contient que des chiffres.
  • Il y a probablement d'autres cas dont je ne suis pas au courant. Vous trouverez peut-être que c'est une ressource utile sur certains des problèmes les plus subtils que vous pouvez rencontrer.

À mon avis, le meilleur moyen d'empêcher généralement l'injection de SQL dans votre application PHP (ou n'importe quelle application Web, d'ailleurs) est de réfléchir à l'architecture de votre application. Si le seul moyen de se protéger contre l'injection SQL est de ne pas oublier d'utiliser une méthode ou une fonction spéciale permettant d'effectuer l'opération The Right Thing à chaque fois que vous parlez à la base de données. De cette façon, ce n'est qu'une question de temps jusqu'à ce que vous oubliez de formater correctement votre requête à un moment donné de votre code.

L'adoption du modèle MVC et d'un framework tel que CakePHP ou CodeIgniter est probablement la bonne voie à suivre: Des tâches courantes telles que la création de requêtes de base de données sécurisées ont été résolues et implémentées de manière centralisée dans de tels frameworks. Ils vous aident à organiser votre application Web de manière judicieuse et vous incitent davantage à charger et à enregistrer des objets qu'à créer en toute sécurité des requêtes SQL uniques.


Chaque réponse ici ne couvre qu’une partie du problème. En fait, nous pouvons ajouter dynamiquement quatre parties de requête différentes:

  • un string
  • un numéro
  • un identifiant
  • un mot clé de syntaxe.

Et les déclarations préparées n'en couvrent que deux.

Mais nous devons parfois rendre notre requête encore plus dynamique en ajoutant des opérateurs ou des identifiants. Nous aurons donc besoin de différentes techniques de protection.

En général, une telle approche de protection est basée sur une liste blanche .

Dans ce cas, chaque paramètre dynamique doit être codé en dur dans votre script et choisi dans cet ensemble. Par exemple, pour faire un ordre dynamique:

$orders  = array("name", "price", "qty"); // Field names
$key     = array_search($_GET['sort'], $orders)); // See if we have such a name
$orderby = $orders[$key]; // If not, first one will be set automatically. smart enuf :)
$query   = "SELECT * FROM `table` ORDER BY $orderby"; // Value is safe

Cependant, il existe un autre moyen de sécuriser les identifiants: l'échappement. Tant que vous avez un identifiant cité, vous pouvez vous échapper des backticks en les doublant.

Une étape supplémentaire consiste à emprunter une idée vraiment brillante consistant à utiliser un espace réservé (un proxy pour représenter la valeur réelle de la requête) à partir des instructions préparées et à inventer un espace réservé d’un autre type - un espace réservé à l’identificateur.

Donc, pour résumer la longue histoire: c'est un espace réservé , une déclaration non préparée peut être considérée comme une solution miracle.

Une recommandation générale peut donc être formulée de la manière suivante: tant que vous ajoutez des pièces dynamiques à la requête en utilisant des espaces réservés (et que ces espaces réservés sont bien traités, bien sûr), vous pouvez être sûr que votre requête est sécurisée .

Néanmoins, il existe un problème avec les mots-clés de la syntaxe SQL (tels que AND , DESC et autres), mais la liste blanche semble être la seule approche dans ce cas.

Mettre à jour

Bien qu’il existe un accord général sur les meilleures pratiques en matière de protection contre les injections SQL, il existe encore de nombreuses mauvaises pratiques. Et certains d’entre eux sont trop profondément ancrés dans l’esprit des utilisateurs de PHP. Par exemple, sur cette page même, il y a (bien que ce soit invisible pour la plupart des visiteurs) plus de 80 réponses supprimées - toutes supprimées par la communauté en raison de la mauvaise qualité ou de la promotion de pratiques mauvaises et obsolètes. Pire encore, certaines des mauvaises réponses ne sont pas supprimées, mais prospères.

Par exemple, there(1) are(2) still(3) many(4) answers(5) , y compris la share suggérant que vous share manuellement une chaîne de caractères - une approche obsolète qui s'est révélée peu sûre.

Ou bien, il existe une réponse légèrement meilleure qui suggère simplement une autre méthode de formatage des chaînes et même la revendique comme la panacée ultime. Bien sûr, ce n'est pas le cas. Cette méthode n’est pas meilleure que le formatage de chaîne classique, mais elle conserve tous ses inconvénients: elle ne s’applique qu’aux chaînes et, comme toute autre mise en forme manuelle, il s’agit essentiellement d’une mesure facultative et non obligatoire, sujette à toute erreur humaine.

Je pense que tout cela est dû à une très vieille superstition, soutenue par des autorités telles que OWASP ou le manuel PHP , qui proclame l’égalité entre les tentatives "d’échappement" et la protection contre les injections SQL.

Indépendamment de ce que le manuel PHP disait depuis des lustres, *_escape_string ne rend nullement les données sûres et n’a jamais été conçu. En plus d'être inutile pour toute partie SQL autre qu'une chaîne, l'échappement manuel est une erreur, car il est manuel et non automatique.

Et OWASP aggrave encore la situation en insistant sur le fait de laisser de côté les utilisateurs, ce qui est une absurdité absolue: il ne devrait pas y en avoir dans le contexte de la protection contre les injections. Chaque variable est potentiellement dangereuse, peu importe la source! Autrement dit, chaque variable doit être correctement formatée pour pouvoir être insérée dans une requête, quelle que soit la source. C'est la destination qui compte. Au moment où un développeur commence à séparer les moutons des chèvres (en déterminant si une variable particulière est "sûre" ou non), il / elle commence son premier pas vers le désastre. Sans compter que même le libellé suggère un échappement en masse au point d’entrée, qui ressemble à la fonction très magique de citations - déjà méprisée, dépréciée et supprimée.

Ainsi, contrairement à ce qui se passe avec "échapper", les instructions préparées sont la mesure qui protège effectivement contre l'injection SQL (le cas échéant).

Si vous n'êtes toujours pas convaincu, voici une explication détaillée que j'ai écrite: Le Guide de l'auto-stoppeur sur la prévention de l'injection SQL , dans laquelle j'ai expliqué toutes ces questions en détail et même rédigé une section entièrement consacrée aux mauvaises pratiques et à leur divulgation.


Je vous recommande d'utiliser PDO (PHP Data Objects) pour exécuter des requêtes SQL paramétrées.

Cela protège non seulement contre l’injection SQL, mais aussi l’accélération des requêtes.

Et en utilisant PDO plutôt que les fonctions mysql_ , mysqli_ et pgsql_ , votre application est un peu plus abstraite de la base de données, dans les rares cas où vous devez changer de fournisseur de base de données.


Quoi que vous utilisiez, assurez-vous de vérifier que votre saisie n'a pas déjà été magic_quotes par magic_quotes ou une autre magic_quotes bien intentionnée, et si nécessaire, passez-la à l'aide de stripslashes ou de quoi que ce soit pour la désinfecter.


Utilisez PDO et les requêtes préparées.

( $conn est un objet PDO )

$stmt = $conn->prepare("INSERT INTO tbl VALUES(:id, :name)");
$stmt->bindValue(':id', $id);
$stmt->bindValue(':name', $name);
$stmt->execute();

Utilisez des instructions préparées et des requêtes paramétrées. Il s'agit d'instructions SQL qui sont envoyées et analysées par le serveur de base de données indépendamment de tout paramètre. De cette manière, il est impossible à un attaquant d'injecter du code SQL malveillant.

Vous avez essentiellement deux options pour y parvenir:

  1. Utilisation de PDO (pour tout pilote de base de données pris en charge):

    $stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
    
    $stmt->execute(array('name' => $name));
    
    foreach ($stmt as $row) {
        // do something with $row
    }
    
  2. Utilisation de MySQLi (pour MySQL):

    $stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
    $stmt->bind_param('s', $name); // 's' specifies the variable type => 'string'
    
    $stmt->execute();
    
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        // do something with $row
    }
    

Si vous vous connectez à une base de données autre que MySQL, vous pouvez vous référer à une deuxième option spécifique au pilote (par exemple, pg_prepare() et pg_execute() pour PostgreSQL). Le PDO est l'option universelle.

Configurer correctement la connexion

Notez que lorsque vous utilisez PDO pour accéder à une base de données MySQL, les instructions réellement préparées ne sont pas utilisées par défaut . Pour résoudre ce problème, vous devez désactiver l'émulation des instructions préparées. Voici un exemple de création d'une connexion à l'aide de PDO:

$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'pass');

$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Dans l'exemple ci-dessus, le mode d'erreur n'est pas strictement nécessaire, mais il est conseillé de l'ajouter . De cette façon, le script ne s’arrêtera pas avec une Fatal Error cas de problème. Et cela donne au développeur la possibilité d’ catch toute erreur (s) PDOException (s) en tant que PDOException .

Ce qui est obligatoire , cependant, est la première ligne setAttribute() , qui indique à PDO de désactiver les instructions préparées émulées et d'utiliser de véritables instructions préparées. Cela permet de s’assurer que la déclaration et les valeurs ne sont pas analysées par PHP avant de l’envoyer au serveur MySQL (ce qui permet à un attaquant éventuel d’injecter du code SQL malveillant).

Bien que vous puissiez définir le charset de charset dans les options du constructeur, il est important de noter que les versions "anciennes" de PHP (<5.3.6) ignoraient en silence le paramètre charset du DSN.

Explication

Ce qui se passe, c'est que l'instruction SQL que vous passez à prepare est analysée et compilée par le serveur de base de données. En spécifiant des paramètres (un ? Ou un paramètre nommé tel que :name dans l'exemple ci-dessus), vous indiquez au moteur de base de données sur lequel vous souhaitez filtrer. Ensuite, lorsque vous appelez execute , l'instruction préparée est combinée aux valeurs de paramètre que vous spécifiez.

La chose importante ici est que les valeurs de paramètre sont combinées avec l'instruction compilée, pas une chaîne SQL. L'injection SQL fonctionne en incitant le script à inclure des chaînes malveillantes lorsqu'il crée du code SQL à envoyer à la base de données. Donc, en envoyant le code SQL séparément des paramètres, vous limitez le risque de vous retrouver avec quelque chose que vous ne souhaitiez pas. Tous les paramètres que vous envoyez en utilisant une instruction préparée seront simplement traités comme des chaînes (bien que le moteur de base de données puisse effectuer certaines optimisations, les paramètres peuvent également se transformer en nombres, bien sûr). Dans l'exemple ci-dessus, si la variable $name contient 'Sarah'; DELETE FROM employees 'Sarah'; DELETE FROM employees le résultat serait simplement une recherche de la chaîne "'Sarah'; DELETE FROM employees" et vous ne vous retrouverez pas avec une table vide .

L’utilisation d’instructions préparées présente un autre avantage: si vous exécutez la même instruction plusieurs fois au cours de la même session, elle ne sera analysée et compilée qu’une seule fois, ce qui vous donnera un gain de rapidité.

Oh, et puisque vous avez demandé comment faire pour une insertion, voici un exemple (en utilisant PDO):

$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');

$preparedStatement->execute(array('column' => $unsafeValue));

Des instructions préparées peuvent-elles être utilisées pour des requêtes dynamiques?

Bien que vous puissiez toujours utiliser des instructions préparées pour les paramètres de requête, la structure de la requête dynamique elle-même ne peut pas être paramétrée et certaines fonctionnalités de la requête ne peuvent pas être paramétrées.

Pour ces scénarios spécifiques, la meilleure chose à faire consiste à utiliser un filtre de liste blanche limitant les valeurs possibles.

// Value whitelist
// $dir can only be 'DESC' otherwise it will be 'ASC'
if (empty($dir) || $dir !== 'DESC') {
   $dir = 'ASC';
}

J'utilise trois méthodes différentes pour éviter que mon application Web ne soit vulnérable à l'injection SQL.

  1. L' utilisation de mysql_real_escape_string(), qui est une fonction prédéfinie dans PHP , et ce code ajouter un slash aux caractères suivants: \x00, \n, \r, \, ', "et \x1a. Transmettez les valeurs d'entrée en tant que paramètres afin de minimiser les risques d'injection SQL.
  2. Le moyen le plus avancé consiste à utiliser des PDO.

J'espère que cela t'aidera.

Considérons la requête suivante:

$iId = mysql_real_escape_string("1 OR 1=1"); $sSql = "SELECT * FROM table WHERE id = $iId";

mysql_real_escape_string () ne protégera pas ici. Si vous utilisez des guillemets simples ('') autour de vos variables dans votre requête, vous êtes protégé contre cela. Voici une solution ci-dessous pour cela:

$iId = (int) mysql_real_escape_string("1 OR 1=1"); $sSql = "SELECT * FROM table WHERE id = $iId";

Cette question a de bonnes réponses à ce sujet.

Je suggère, l'utilisation de PDO est la meilleure option.

Modifier:

mysql_real_escape_string()est obsolète depuis PHP 5.5.0. Utilisez soit mysqli ou PDO.

Une alternative à mysql_real_escape_string () est

string mysqli_real_escape_string ( mysqli $link , string $escapestr )

Exemple:

$iId = $mysqli->real_escape_string("1 OR 1=1");
$mysqli->query("SELECT * FROM table WHERE id = $iId");

Je pense que si quelqu'un veut utiliser PHP et MySQL ou un autre serveur de base de données:

  1. Pensez à l’apprentissage PDO (PHP Data Objects) - c’est une couche d’accès à une base de données offrant une méthode uniforme d’accès à plusieurs bases de données.
  2. Pensez à apprendre MySQLi
  3. Utilisez des fonctions PHP natives telles que: strip_tags , mysql_real_escape_string() ou si variable numérique, juste (int)$foo. En savoir plus sur le type de variables en PHP here . Si vous utilisez des bibliothèques telles que PDO ou MySQLi, utilisez toujours PDO::quote() et mysqli_real_escape_string() .

Exemples de bibliothèques:

---- AOP

----- Aucun espace réservé - mûr pour l'injection SQL! C'est mauvais

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values ($name, $addr, $city)");

----- espaces réservés sans nom

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values (?, ?, ?);

----- Espaces réservés nommés

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) value (:name, :addr, :city)");

--- MySQLi

$request = $mysqliConnection->prepare('
       SELECT * FROM trainers
       WHERE name = ?
       AND email = ?
       AND last_login > ?');

    $query->bind_param('first_param', 'second_param', $mail, time() - 3600);
    $query->execute();

PS :

PDO gagne cette bataille avec facilité. Avec la prise en charge de douze pilotes de base de données différents et de paramètres nommés, nous pouvons ignorer la petite perte de performances et nous habituer à son API. Du point de vue de la sécurité, les deux sont sécurisés tant que le développeur les utilise comme ils sont censés être utilisés

Toutefois, bien que PDO et MySQLi soient assez rapides, MySQLi est extrêmement rapide dans les tests de performance: environ 2,5% pour les instructions non préparées et environ 6,5% pour les déclarations préparées.

Et testez chaque requête dans votre base de données. C'est un meilleur moyen de prévenir l'injection.


** Avertissement: l'approche décrite dans cette réponse ne s'applique qu'à des scénarios très spécifiques et n'est pas sécurisée, car les attaques par injection SQL ne reposent pas uniquement sur la possibilité d'injecter X=Y. **

Si les attaquants essaient de pirater le formulaire via la $_GETvariable PHP ou avec la chaîne de requête de l'URL, vous pourrez les intercepter s'ils ne sont pas sécurisés.

RewriteCond %{QUERY_STRING} ([0-9]+)=([0-9]+)
RewriteRule ^(.*) ^/track.php

Parce que 1=1, 2=2, 1=2, 2=1, 1+1=2, etc ... sont les questions communes à une base de données SQL d'un attaquant. Peut-être aussi est-il utilisé par de nombreuses applications de piratage.

Mais vous devez faire attention à ne pas réécrire une requête sécurisée de votre site. Le code ci-dessus vous donne un conseil, pour réécrire ou rediriger (cela dépend de vous) cette chaîne de requête dynamique spécifique au piratage dans une page qui stockera l' adresse IP de l'attaquant , ou MÊME LEURS COOKIES, son historique, son navigateur ou tout autre élément sensible. informations, afin que vous puissiez les traiter plus tard en interdisant leur compte ou en contactant les autorités.


MYSQLi est MYSQLi d’empêcher les injections SQL d’ utiliser PDO et MYSQLi , mais si vous souhaitez réellement utiliser des fonctions et des requêtes MySQL, il est préférable d’utiliser

mysql_real_escape_string()

$unsafe_variable = mysql_real_escape_string($_POST['user_input']);

Il existe plus de possibilités pour empêcher cela: comme identifier - si l'entrée est une chaîne, un nombre, un caractère ou un tableau, il y a tellement de fonctions intégrées pour le détecter. En outre, il serait préférable d’utiliser ces fonctions pour vérifier les données d’entrée.

is_string

$unsafe_variable = (is_string($_POST['user_input']) ? $_POST['user_input'] : '');

is_numeric

$unsafe_variable = (is_numeric($_POST['user_input']) ? $_POST['user_input'] : '');

Et il est tellement préférable d'utiliser ces fonctions pour vérifier les données d'entrée mysql_real_escape_string.


En utilisant cette fonction PHP, mysql_escape_string()vous pouvez obtenir une bonne prévention rapidement.

Par exemple:

SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."'

mysql_escape_string - Echappe une chaîne pour l'utiliser dans un mysql_query

Pour plus de prévention, vous pouvez ajouter à la fin ...

wHERE 1=1   or  LIMIT 1

Enfin vous obtenez:

SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."' LIMIT 1

Il existe de nombreuses manières d'empêcher les injections SQL et autres piratages SQL. Vous pouvez facilement le trouver sur Internet (Recherche Google). Bien sûr, le PDO est l’une des bonnes solutions. Mais je voudrais vous suggérer une bonne prévention des liens de SQL Injection.

Qu'est-ce que l'injection SQL et comment prévenir

Manuel PHP pour l'injection SQL

Explication Microsoft de l'injection SQL et de la prévention en PHP

et d'autres comme Prévenir l'injection SQL avec MySQL et PHP

Maintenant, pourquoi avez-vous besoin d'empêcher votre requête d'injection SQL?

Je voudrais vous faire savoir: pourquoi essayons-nous d'empêcher l'injection SQL avec un court exemple ci-dessous:

Requête pour correspondance d'authentification de connexion:

$query="select * from users where email='".$_POST['email']."' and password='".$_POST['password']."' ";

Maintenant, si quelqu'un (un pirate informatique) met

$_POST['email']= [email protected]' OR '1=1

et mot de passe quoi que ce soit ....

La requête ne sera analysée dans le système que jusqu'à:

$query="select * from users where email='[email protected]' OR '1=1';

L'autre partie sera éliminée. Alors, que va-t-il se passer? Un utilisateur non autorisé (pirate informatique) pourra se connecter en tant qu'administrateur sans avoir son mot de passe. Maintenant, il peut faire tout ce que peuvent faire les administrateurs et les courriers électroniques. Vous voyez, c'est très dangereux si l'injection SQL n'est pas empêchée.


Je privilégie les procédures stockées ( MySQL prend en charge les procédures stockées depuis la version 5.0 ) du point de vue de la sécurité - les avantages sont -

  1. La plupart des bases de données (y compris MySQL ) permettent de limiter l'accès des utilisateurs à l'exécution de procédures stockées. Le contrôle d'accès de sécurité à granularité fine est utile pour empêcher les attaques d'escalade de privilèges. Cela empêche les applications compromises d'exécuter directement du SQL sur la base de données.
  2. Ils font abstraction de la requête SQL brute de l’application afin que moins d’informations sur la structure de la base de données soient disponibles pour l’application. Cela rend plus difficile la compréhension de la structure sous-jacente de la base de données et la conception d’attaques appropriées.
  3. Ils n'acceptent que les paramètres, les avantages des requêtes paramétrées sont donc là. Bien sûr - IMO, vous devez encore purifier votre saisie - surtout si vous utilisez du SQL dynamique dans la procédure stockée.

Les inconvénients sont -

  1. Ils (procédures stockées) sont difficiles à maintenir et ont tendance à se multiplier très rapidement. Cela rend leur gestion un problème.
  2. Ils ne conviennent pas très bien aux requêtes dynamiques. S'ils sont conçus pour accepter le code dynamique en tant que paramètres, de nombreux avantages sont annulés.

L'alternative simple à ce problème pourrait être résolue en accordant les autorisations appropriées dans la base de données elle-même. Par exemple: si vous utilisez une base de données mysql, entrez-la dans la base de données via le terminal ou l'interface utilisateur fournie et suivez cette commande

 GRANT SELECT, INSERT, DELETE ON database TO [email protected]'localhost' IDENTIFIED BY 'password';

Cela empêchera l'utilisateur de se limiter uniquement à la requête spécifiée. Supprimez l'autorisation de suppression et les données ne seraient jamais supprimées de la requête renvoyée de la page php. La deuxième chose à faire est de vider les privilèges pour que le mysql actualise les permissions et les mises à jour.

FLUSH PRIVILEGES; 

plus d'informations sur flush .

Pour voir les privilèges actuels de l'utilisateur, lancez la requête suivante.

select * from mysql.user where User='username';

En savoir plus sur GRANT .


Si possible, définissez les types de vos paramètres. Mais cela ne fonctionne que sur des types simples comme int, bool et float.

$unsafe_variable = $_POST['user_id'];

$safe_variable = (int)$unsafe_variable ;

mysqli_query($conn, "INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

Si vous souhaitez tirer parti des moteurs de cache, tels que Redis ou Memcached , DALMP pourrait peut-être être un choix. Il utilise purement MySQLi . Vérifiez ceci: Couche d'abstraction de base de données DALMP pour MySQL avec PHP.

En outre, vous pouvez "préparer" vos arguments avant de préparer votre requête afin de pouvoir créer des requêtes dynamiques et disposer à la fin d'une requête d'instructions entièrement préparée. Couche d'abstraction de base de données DALMP pour MySQL avec PHP.


Une méthode simple consisterait à utiliser un environnement PHP tel que CodeIgniter ou Laravel qui intègre des fonctionnalités telles que le filtrage et l'enregistrement actif, de sorte que vous n'ayez pas à vous soucier de ces nuances.





sql-injection