Les instructions préparées par PDO sont-elles suffisantes pour empêcher l'injection SQL?

StackOverflow https://stackoverflow.com/questions/134099

Question

Disons que j'ai un code comme celui-ci:

$dbh = new PDO("blahblah");

$stmt = $dbh->prepare('SELECT * FROM users where username = :username');
$stmt->execute( array(':username' => 

Disons que j'ai un code comme celui-ci:

<*>

La documentation de PDO indique:

  

Il n'est pas nécessaire de citer les paramètres des instructions préparées; le conducteur le gère pour vous.

Est-ce vraiment tout ce que j'ai à faire pour éviter les injections SQL? Est-ce vraiment si facile?

Vous pouvez supposer que MySQL fait une différence. De plus, je ne suis vraiment curieux que de l’utilisation des instructions préparées contre l’injection SQL. Dans ce contexte, je ne me soucie pas de XSS ni d’autres vulnérabilités possibles.

REQUEST['username']) );

La documentation de PDO indique:

  

Il n'est pas nécessaire de citer les paramètres des instructions préparées; le conducteur le gère pour vous.

Est-ce vraiment tout ce que j'ai à faire pour éviter les injections SQL? Est-ce vraiment si facile?

Vous pouvez supposer que MySQL fait une différence. De plus, je ne suis vraiment curieux que de l’utilisation des instructions préparées contre l’injection SQL. Dans ce contexte, je ne me soucie pas de XSS ni d’autres vulnérabilités possibles.

Était-ce utile?

La solution

La réponse courte est NON , PDO prépare ne vous protégera pas de toutes les attaques par injection SQL possibles. Pour certains cas obscurs.

J'adapte cette réponse pour parler de PDO ...

La réponse longue n'est pas si facile. Il est basé sur une attaque présentée ici .

L'attaque

Commençons donc par montrer l'attaque ...

$pdo->query('SET NAMES gbk');
$var = "\xbf\x27 OR 1=1 /*";
$query = 'SELECT * FROM test WHERE name = ? LIMIT 1';
$stmt = $pdo->prepare($query);
$stmt->execute(array($var));

Dans certaines circonstances, cela renverra plus d'une ligne. Disséquons ce qui se passe ici:

  1. Sélection d'un jeu de caractères

    $pdo->query('SET NAMES gbk');
    

    Pour que cette attaque fonctionne, nous avons besoin du codage attendu par le serveur sur la connexion pour coder ' comme en ASCII, par exemple 0x27 et avoir un caractère dont l'octet final est un \ ASCII 0x5c . Il s’avère que 5 de ces encodages sont pris en charge dans MySQL 5.6 par défaut: big5 , cp932 , gb2312 , gbk et sjis . Nous allons sélectionner gbk ici.

    Maintenant, il est très important de noter l'utilisation de SET NAMES ici. Cela définit le jeu de caractères SUR LE SERVEUR . Il existe un autre moyen de le faire, mais nous y arriverons assez tôt.

  2. La charge utile

    La charge que nous allons utiliser pour cette injection commence par la séquence d'octets 0xbf27 . Dans gbk , il s'agit d'un caractère multi-octets non valide; dans latin1 , il s'agit de la chaîne & # 191; '. Notez que dans latin1 et gbk , 0x27 est à lui seul un ' littéral. personnage.

    Nous avons choisi cette charge parce que, si nous appelions includeslashes () , nous insérerions un \ ASCII, c'est-à-dire 0x5c , avant le caractère '. Nous finirions donc avec 0xbf5c27 , ce qui dans gbk correspond à une séquence de deux caractères: 0xbf5c suivi de 0x27 . Ou, en d'autres termes, un caractère valide suivi d'un ' non échappé. Mais nous n'utilisons pas addedlashes () . Passons à l'étape suivante ...

  3. $ stmt- > execute ()

    La chose importante à comprendre ici est que PDO par défaut NOT ne fait pas de vraies instructions préparées. Il les émule (pour MySQL). Par conséquent, PDO construit en interne la chaîne de requête en appelant mysql_real_escape_string () (la fonction MySQL C API) sur chaque valeur de chaîne liée.

    L'appel de l'API C à mysql_real_escape_string () diffère de addedlashes () en ce qu'il connaît le jeu de caractères de connexion. Ainsi, il peut exécuter correctement l'échappement pour le jeu de caractères attendu par le serveur. Cependant, jusqu'à présent, le client pense que nous utilisons toujours latin1 pour la connexion, car nous ne lui avons jamais dit le contraire. Nous avons dit au serveur que nous utilisions gbk , mais le client pense toujours que c'est latin1 .

    Par conséquent, l'appel à mysql_real_escape_string () insère la barre oblique inverse, et nous avons un caractère ' libre et suspendu dans notre caractère "échappé". contenu! En fait, si nous examinions $ var dans le jeu de caractères gbk , nous verrions:

    縗' OR 1=1 /*

    C’est exactement ce que requiert l’attaque.

  4. La requête

    Cette partie est juste une formalité, mais voici la requête rendue:

    SELECT * FROM test WHERE name = '縗' OR 1=1 /*' LIMIT 1
    

Félicitations, vous venez d’attaquer avec succès un programme utilisant les instructions préparées PDO ...

La solution simple

Maintenant, il est intéressant de noter que vous pouvez empêcher cela en désactivant les instructions préparées émulées:

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Ceci donnera habituellement une déclaration préparée vraie (c’est-à-dire que les données sont envoyées dans un paquet séparé de la requête). Toutefois, sachez que PDO restera silencieux fallback répertorié dans le manuel, mais veillez à sélectionner la version de serveur appropriée).

Le correctif correct

Le problème ici est que nous n’avons pas appelé mysql_set_charset () de l’API C au lieu de SET NAMES . Si nous le faisions, tout irait bien si nous utilisons une version de MySQL depuis 2006.

Si vous utilisez une version antérieure de MySQL, un bug dans mysql_real_escape_string () signifiait que les caractères multi-octets non valides tels que ceux de notre charge utile étaient traités comme des octets simples à des fins d'échappement même si le client avait été correctement informé du codage de connexion cette attaque réussirait toujours. Le bogue a été corrigé dans MySQL 4.1.20 , 5.0.22 et 5.1.11 .

Mais le pire, c'est que PDO n'a pas exposé l'API C pour mysql_set_charset () jusqu'à la version 5.3.6. Ainsi, dans les versions précédentes, il ne pouvait pas / strong> empêchez cette attaque pour chaque commande possible!  Il est maintenant exposé en tant que paramètre DSN , qui devrait être utilisé au lieu de SET NAMES ...

La grâce salvatrice

Comme nous l'avons dit au début, pour que cette attaque fonctionne, la connexion à la base de données doit être codée à l'aide d'un jeu de caractères vulnérable. utf8mb4 n'est pas vulnérable et capable de prendre en charge tous les caractères Unicode: vous pouvez donc choisir de l’utiliser à la place & # 8212; mais il n’est disponible que depuis MySQL 5.5.3. Une alternative est utf8 , qui est également non vulnérable et peut prendre en charge l’ensemble des caractères Unicode Basique Plan multilingue .

Vous pouvez également activer le NO_BACKSLASH_ESCAPES Le mode SQL, qui modifie (entre autres choses) le fonctionnement de mysql_real_escape_string () . Lorsque ce mode est activé, 0x27 sera remplacé par 0x2727 plutôt que 0x5c27 et le processus d'échappement ne pourra donc pas créer . les caractères de l'un des encodages vulnérables où ils n'existaient pas auparavant (c'est-à-dire que 0xbf27 est toujours 0xbf27 etc.) & # 8212; le serveur rejettera toujours la chaîne comme invalide . Toutefois, consultez la réponse de @ eggyal pour connaître une autre vulnérabilité pouvant découler de l'utilisation de ce mode SQL (mais pas avec PDO). / p>

Exemples sécurisés

Les exemples suivants sont sécurisés:

mysql_query('SET NAMES utf8');
$var = mysql_real_escape_string("\xbf\x27 OR 1=1 /*");
mysql_query("SELECT * FROM test WHERE name = '$var' LIMIT 1");

Parce que le serveur attend utf8 ...

mysql_set_charset('gbk');
$var = mysql_real_escape_string("\xbf\x27 OR 1=1 /*");
mysql_query("SELECT * FROM test WHERE name = '$var' LIMIT 1");

Parce que nous avons correctement défini le jeu de caractères afin que le client et le serveur correspondent.

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->query('SET NAMES gbk');
$stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1');
$stmt->execute(array("\xbf\x27 OR 1=1 /*"));

Parce que nous avons désactivé les instructions préparées émulées.

$pdo = new PDO('mysql:host=localhost;dbname=testdb;charset=gbk', $user, $password);
$stmt = $pdo->prepare('SELECT * FROM test WHERE name = ? LIMIT 1');
$stmt->execute(array("\xbf\x27 OR 1=1 /*"));

Parce que nous avons défini correctement le jeu de caractères.

$mysqli->query('SET NAMES gbk');
$stmt = $mysqli->prepare('SELECT * FROM test WHERE name = ? LIMIT 1');
$param = "\xbf\x27 OR 1=1 /*";
$stmt->bind_param('s', $param);
$stmt->execute();

Parce que MySQLi effectue de vraies instructions préparées tout le temps.

Conclusion

Si vous:

  • Utiliser les versions modernes de MySQL (version 5.1, versions 5.5, 5.6, etc.) AND du paramètre charset DSN du PDO (en PHP & # 8805; 5.3.6)

OU

  • N'utilisez pas de jeu de caractères vulnérable pour le codage de la connexion (vous utilisez uniquement utf8 / latin1 / ascii / etc)

OU

  • Activer NO_BACKSLASH_ESCAPES mode SQL

Vous êtes à 100% en sécurité.

Sinon, vous êtes vulnérable même si vous utilisez des instructions préparées PDO ...

Addendum

Je travaille lentement sur un correctif pour changer la valeur par défaut afin de ne pas émuler, cela prépare une future version de PHP. Le problème que je rencontre est que BEAUCOUP de tests sont rompus lorsque je le fais. Un des problèmes est que les préparations émulées ne génèrent que des erreurs de syntaxe lors de l'exécution, mais true, prépare des erreurs lors de la préparation. Cela peut donc poser problème (et cela fait partie de la raison pour laquelle les tests échouent).

Autres conseils

Les instructions préparées / requêtes paramétrées sont généralement suffisantes pour empêcher une injection 1er ordre sur cette instruction * . Si vous utilisez du code SQL dynamique non vérifié ailleurs dans votre application, vous êtes toujours vulnérable aux injections 2e ordre .

L'injection de second ordre signifie que les données ont été cyclées dans la base de données une fois avant d'être incluses dans une requête et sont beaucoup plus difficiles à extraire. Selon mes connaissances, vous ne verrez presque jamais de véritables attaques d'ingénierie de second ordre, car il est généralement plus facile pour les attaquants de se familiariser avec l'ingénierie sociale, mais il arrive parfois que des bogues de second ordre apparaissent en raison de caractères extra bénins ou similaire.

Vous pouvez effectuer une attaque par injection de second ordre lorsque vous pouvez faire en sorte qu'une valeur soit stockée dans une base de données utilisée ultérieurement en tant que littéral dans une requête. Par exemple, supposons que vous entrez les informations suivantes comme nouveau nom d'utilisateur lors de la création d'un compte sur un site Web (en supposant que la base de données MySQL est utilisée pour cette question):

' + (SELECT UserName + '_' + Password FROM Users LIMIT 1) + '

S'il n'y a pas d'autres restrictions sur le nom d'utilisateur, une instruction préparée garantirait toujours que la requête incorporée ci-dessus ne s'exécute pas au moment de l'insertion et stocke la valeur correctement dans la base de données. Cependant, imaginez que l'application récupère ultérieurement votre nom d'utilisateur dans la base de données et utilise la concaténation de chaînes pour inclure cette valeur dans une nouvelle requête. Vous pourriez peut-être voir le mot de passe de quelqu'un d'autre. Comme les premiers noms de la table users ont tendance à être des administrateurs, vous venez peut-être de céder la ferme. (Remarque: ceci est une raison de plus de ne pas stocker les mots de passe en texte brut!)

Nous voyons donc que les instructions préparées sont suffisantes pour une requête unique, mais ne suffisent pas, en elles-mêmes, à se protéger contre les attaques par injection SQL dans l'ensemble d'une application, car elles ne disposent pas d'un mécanisme permettant de les appliquer. que tout accès à une base de données au sein de l'application utilise un code sécurisé. Toutefois, utilisé dans le cadre d’une bonne conception d’applications, pouvant inclure des pratiques telles que la révision de code ou l’analyse statique, ou l’utilisation d’un ORM, d’une couche de données ou d’une couche de service limitant les instructions dynamiques SQL - sont l'outil principal de résolution du problème d'injection SQL. Si vous suivez de bons principes de conception d'applications, tels que votre accès aux données est séparé du reste de votre. programme, il devient facile d’appliquer ou de vérifier que chaque requête utilise correctement le paramétrage. Dans ce cas, l'injection de SQL (premier et deuxième ordre) est complètement empêchée.

* Il s'avère que MySql / PHP est juste d'accord pour gérer les paramètres lorsque des caractères larges sont impliqués et qu'il existe encore un rare le cas décrit dans la autre réponse très votée ici qui permet à l'injection de glisser à travers une requête paramétrée.

Non, ils ne sont pas toujours.

Cela dépend si vous autorisez ou non la saisie de l'utilisateur dans la requête elle-même. Par exemple:

$dbh = new PDO("blahblah");

$tableToUse = 

Non, ils ne sont pas toujours.

Cela dépend si vous autorisez ou non la saisie de l'utilisateur dans la requête elle-même. Par exemple:

$dbh = new PDO("blahblah");

$tableToUse = 

Non, ils ne sont pas toujours.

Cela dépend si vous autorisez ou non la saisie de l'utilisateur dans la requête elle-même. Par exemple:

$dbh = new PDO("blahblah");

$tableToUse = 

Non, ils ne sont pas toujours.

Cela dépend si vous autorisez ou non la saisie de l'utilisateur dans la requête elle-même. Par exemple:

$stmt = $dbh->prepare('SELECT * FROM foo ORDER BY :userSuppliedData');

serait vulnérable aux injections SQL et utiliser des instructions préparées dans cet exemple ne fonctionnera pas, car l'entrée utilisateur est utilisée comme identifiant et non comme donnée. La bonne réponse ici serait d’utiliser une sorte de filtrage / validation comme:

<*>

Remarque: vous ne pouvez pas utiliser PDO pour lier des données en dehors de DDL (langage de définition de données), c’est-à-dire que cela ne fonctionne pas:

<*>

La raison pour laquelle ce qui précède ne fonctionne pas est que DESC et ASC ne sont pas des données . PDO ne peut échapper que pour données . Deuxièmement, vous ne pouvez même pas mettre ' entre guillemets. Le seul moyen d'autoriser le tri choisi par l'utilisateur consiste à filtrer manuellement et à vérifier qu'il s'agit bien de DESC ou de ASC .

GET['userTable']; $stmt = $dbh->prepare('SELECT * FROM ' . $tableToUse . ' where username = :username'); $stmt->execute( array(':username' =>

Non, ils ne sont pas toujours.

Cela dépend si vous autorisez ou non la saisie de l'utilisateur dans la requête elle-même. Par exemple:

<*>

serait vulnérable aux injections SQL et utiliser des instructions préparées dans cet exemple ne fonctionnera pas, car l'entrée utilisateur est utilisée comme identifiant et non comme donnée. La bonne réponse ici serait d’utiliser une sorte de filtrage / validation comme:

<*>

Remarque: vous ne pouvez pas utiliser PDO pour lier des données en dehors de DDL (langage de définition de données), c’est-à-dire que cela ne fonctionne pas:

<*>

La raison pour laquelle ce qui précède ne fonctionne pas est que DESC et ASC ne sont pas des données . PDO ne peut échapper que pour données . Deuxièmement, vous ne pouvez même pas mettre ' entre guillemets. Le seul moyen d'autoriser le tri choisi par l'utilisateur consiste à filtrer manuellement et à vérifier qu'il s'agit bien de DESC ou de ASC .

REQUEST['username']) );

serait vulnérable aux injections SQL et utiliser des instructions préparées dans cet exemple ne fonctionnera pas, car l'entrée utilisateur est utilisée comme identifiant et non comme donnée. La bonne réponse ici serait d’utiliser une sorte de filtrage / validation comme:

<*>

Remarque: vous ne pouvez pas utiliser PDO pour lier des données en dehors de DDL (langage de définition de données), c’est-à-dire que cela ne fonctionne pas:

<*>

La raison pour laquelle ce qui précède ne fonctionne pas est que DESC et ASC ne sont pas des données . PDO ne peut échapper que pour données . Deuxièmement, vous ne pouvez même pas mettre ' entre guillemets. Le seul moyen d'autoriser le tri choisi par l'utilisateur consiste à filtrer manuellement et à vérifier qu'il s'agit bien de DESC ou de ASC .

GET['userTable']; $allowedTables = array('users','admins','moderators'); if (!in_array($tableToUse,$allowedTables)) $tableToUse = 'users'; $stmt = $dbh->prepare('SELECT * FROM ' . $tableToUse . ' where username = :username'); $stmt->execute( array(':username' =>

Non, ils ne sont pas toujours.

Cela dépend si vous autorisez ou non la saisie de l'utilisateur dans la requête elle-même. Par exemple:

$dbh = new PDO("blahblah");

$tableToUse = 

Non, ils ne sont pas toujours.

Cela dépend si vous autorisez ou non la saisie de l'utilisateur dans la requête elle-même. Par exemple:

<*>

serait vulnérable aux injections SQL et utiliser des instructions préparées dans cet exemple ne fonctionnera pas, car l'entrée utilisateur est utilisée comme identifiant et non comme donnée. La bonne réponse ici serait d’utiliser une sorte de filtrage / validation comme:

<*>

Remarque: vous ne pouvez pas utiliser PDO pour lier des données en dehors de DDL (langage de définition de données), c’est-à-dire que cela ne fonctionne pas:

<*>

La raison pour laquelle ce qui précède ne fonctionne pas est que DESC et ASC ne sont pas des données . PDO ne peut échapper que pour données . Deuxièmement, vous ne pouvez même pas mettre ' entre guillemets. Le seul moyen d'autoriser le tri choisi par l'utilisateur consiste à filtrer manuellement et à vérifier qu'il s'agit bien de DESC ou de ASC .

GET['userTable']; $stmt = $dbh->prepare('SELECT * FROM ' . $tableToUse . ' where username = :username'); $stmt->execute( array(':username' =>

Non, ils ne sont pas toujours.

Cela dépend si vous autorisez ou non la saisie de l'utilisateur dans la requête elle-même. Par exemple:

<*>

serait vulnérable aux injections SQL et utiliser des instructions préparées dans cet exemple ne fonctionnera pas, car l'entrée utilisateur est utilisée comme identifiant et non comme donnée. La bonne réponse ici serait d’utiliser une sorte de filtrage / validation comme:

<*>

Remarque: vous ne pouvez pas utiliser PDO pour lier des données en dehors de DDL (langage de définition de données), c’est-à-dire que cela ne fonctionne pas:

<*>

La raison pour laquelle ce qui précède ne fonctionne pas est que DESC et ASC ne sont pas des données . PDO ne peut échapper que pour données . Deuxièmement, vous ne pouvez même pas mettre ' entre guillemets. Le seul moyen d'autoriser le tri choisi par l'utilisateur consiste à filtrer manuellement et à vérifier qu'il s'agit bien de DESC ou de ASC .

REQUEST['username']) );

serait vulnérable aux injections SQL et utiliser des instructions préparées dans cet exemple ne fonctionnera pas, car l'entrée utilisateur est utilisée comme identifiant et non comme donnée. La bonne réponse ici serait d’utiliser une sorte de filtrage / validation comme:

<*>

Remarque: vous ne pouvez pas utiliser PDO pour lier des données en dehors de DDL (langage de définition de données), c’est-à-dire que cela ne fonctionne pas:

<*>

La raison pour laquelle ce qui précède ne fonctionne pas est que DESC et ASC ne sont pas des données . PDO ne peut échapper que pour données . Deuxièmement, vous ne pouvez même pas mettre ' entre guillemets. Le seul moyen d'autoriser le tri choisi par l'utilisateur consiste à filtrer manuellement et à vérifier qu'il s'agit bien de DESC ou de ASC .

REQUEST['username']) );

serait vulnérable aux injections SQL et utiliser des instructions préparées dans cet exemple ne fonctionnera pas, car l'entrée utilisateur est utilisée comme identifiant et non comme donnée. La bonne réponse ici serait d’utiliser une sorte de filtrage / validation comme:

<*>

Remarque: vous ne pouvez pas utiliser PDO pour lier des données en dehors de DDL (langage de définition de données), c’est-à-dire que cela ne fonctionne pas:

<*>

La raison pour laquelle ce qui précède ne fonctionne pas est que DESC et ASC ne sont pas des données . PDO ne peut échapper que pour données . Deuxièmement, vous ne pouvez même pas mettre ' entre guillemets. Le seul moyen d'autoriser le tri choisi par l'utilisateur consiste à filtrer manuellement et à vérifier qu'il s'agit bien de DESC ou de ASC .

GET['userTable']; $stmt = $dbh->prepare('SELECT * FROM ' . $tableToUse . ' where username = :username'); $stmt->execute( array(':username' =>

Non, ils ne sont pas toujours.

Cela dépend si vous autorisez ou non la saisie de l'utilisateur dans la requête elle-même. Par exemple:

<*>

serait vulnérable aux injections SQL et utiliser des instructions préparées dans cet exemple ne fonctionnera pas, car l'entrée utilisateur est utilisée comme identifiant et non comme donnée. La bonne réponse ici serait d’utiliser une sorte de filtrage / validation comme:

<*>

Remarque: vous ne pouvez pas utiliser PDO pour lier des données en dehors de DDL (langage de définition de données), c’est-à-dire que cela ne fonctionne pas:

<*>

La raison pour laquelle ce qui précède ne fonctionne pas est que DESC et ASC ne sont pas des données . PDO ne peut échapper que pour données . Deuxièmement, vous ne pouvez même pas mettre ' entre guillemets. Le seul moyen d'autoriser le tri choisi par l'utilisateur consiste à filtrer manuellement et à vérifier qu'il s'agit bien de DESC ou de ASC .

REQUEST['username']) );

serait vulnérable aux injections SQL et utiliser des instructions préparées dans cet exemple ne fonctionnera pas, car l'entrée utilisateur est utilisée comme identifiant et non comme donnée. La bonne réponse ici serait d’utiliser une sorte de filtrage / validation comme:

<*>

Remarque: vous ne pouvez pas utiliser PDO pour lier des données en dehors de DDL (langage de définition de données), c’est-à-dire que cela ne fonctionne pas:

<*>

La raison pour laquelle ce qui précède ne fonctionne pas est que DESC et ASC ne sont pas des données . PDO ne peut échapper que pour données . Deuxièmement, vous ne pouvez même pas mettre ' entre guillemets. Le seul moyen d'autoriser le tri choisi par l'utilisateur consiste à filtrer manuellement et à vérifier qu'il s'agit bien de DESC ou de ASC .

Oui, c'est suffisant. La manière dont les attaques par type d'injection fonctionnent consiste à demander à un interprète (la base de données) d'évaluer quelque chose, qui aurait dû être des données, comme s'il s'agissait de code. Cela n’est possible que si vous mélangez du code et des données sur le même support (par exemple, lorsque vous construisez une requête sous forme de chaîne).

Les requêtes paramétrées fonctionnent en envoyant le code et les données séparément, de sorte qu'il serait jamais possible de trouver un trou dans cette tâche.

Vous pouvez toujours être vulnérable à d’autres attaques de type injection. Par exemple, si vous utilisez les données d'une page HTML, vous pourriez être sujet à des attaques de type XSS.

Non, cela ne suffit pas (dans certains cas)! Par défaut, PDO utilise des instructions préparées émulées lorsque MySQL est utilisé comme pilote de base de données. Vous devez toujours désactiver les instructions préparées émulées lorsque vous utilisez MySQL et PDO:

$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

Une autre chose à faire est de toujours définir le codage correct de la base de données:

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

Voir aussi cette question connexe: Comment puis-je empêcher SQL injection en PHP?

Notez également que cela ne concerne que le côté base de données que vous auriez toujours à surveiller vous-même lors de l'affichage des données. Par exemple. en utilisant htmlspecialchars () à nouveau avec le style de codage et de citation correct.

Personnellement, je voudrais toujours exécuter une forme d’assainissement sur les données d’abord, car vous ne pouvez jamais vous fier à une entrée utilisateur. Toutefois, lorsque vous utilisez une liaison entre paramètres et espaces réservés, les données saisies sont envoyées séparément au serveur avec l’instruction SQL, puis liées entre elles. La clé ici est que cela lie les données fournies à un type spécifique et à une utilisation spécifique et élimine toute possibilité de modifier la logique de l'instruction SQL.

Si vous voulez empêcher l’injection SQL front-end en utilisant des contrôles html ou js, vous devez considérer que les contrôles en amont sont "contournables".

Vous pouvez désactiver js ou modifier un motif avec un outil de développement frontal (intégré à Firefox ou à Chrome de nos jours).

Ainsi, afin d’empêcher l’injection de code SQL, il serait bon de nettoyer le backend de la date d’entrée dans votre contrôleur.

J'aimerais vous suggérer d'utiliser la fonction PHP native filter_input () afin de nettoyer les valeurs GET et INPUT.

Si vous souhaitez renforcer la sécurité, pour les requêtes de base de données sensibles, j'aimerais vous suggérer d'utiliser une expression régulière pour valider le format des données. preg_match () vous aidera dans ce cas! Mais prends soin de toi! Le moteur Regex n'est pas si léger. Utilisez-le uniquement si nécessaire, sinon les performances de votre application diminueront.

La sécurité a un coût, mais ne perdez pas votre performance!

Exemple simple:

si vous souhaitez vérifier si une valeur reçue de GET est un nombre inférieur à 99     if (! preg_match ('/ [0-9] {1,2} /')) {...} est plus lourd de

if (isset($value) && intval($value)) <99) {...}

La réponse finale est donc: "Non! Les déclarations préparées par AOP n’empêchent pas tous les types d’injections SQL; Cela n'empêche pas les valeurs inattendues, juste la concaténation inattendue

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top