2010-08-12 14 views
1

Je me sers PDO pour parler à ma base de données, et je me demande si un type de coulée comme celui-ciCette injection de requête est-elle fiable?

$dbh->query("SELECT * FROM recipes WHERE id=".(int)$id); 

est suffisante pour empêcher l'injection sql? Dans ce cas, $ id est toujours un entier.

Je me demande aussi ce qui serait un bon moyen d'empêcher une injection dans ce genre d'instruction si la variable était une chaîne.

+3

Le meilleur moyen est d'utiliser des requêtes paramétrées. – Fosco

+0

Désolé pour une question stupide, mais comment puis-je le faire dans ce cas? – Michael

+0

Le meilleur moyen est d'utiliser des procédures stockées paramétrées. –

Répondre

4

Oui. Casting à int empêche toutes les possibilités d'injection SQL méchant.

Si la variable était une chaîne, vous devez utiliser prepared statements pour la transmettre.

$sql = 'SELECT name, colour, calories 
    FROM fruit 
    WHERE calories < :calories AND colour = :colour'; 
$sth = $dbh->prepare($sql); 
$sth->execute(array(':calories' => 150, ':colour' => 'red')); 
$red = $sth->fetchAll(); 
0

Vous devez échapper les noms de table et sur le terrain dans la requête:

$dbh->query("SELECT * FROM `recipes` WHERE `id=`'".(int)$id."'"); 
+0

deux erreurs dans la tentative d'amélioration ...: -O –

+0

Ce n'est pas un * must * à moins que ce soit un mot-clé, mais oui, c'est une bonne pratique de le faire quand même. – casablanca

3

, une meilleure approche Puisque vous utilisez déjà PDO à utiliser:

C'est beaucoup mieux:

$dbh->prepare("SELECT * FROM recipes WHERE id = ?"); 
$dbh->bindParam(1, (int) $id); 
// more code..... 
+0

Donc, si je les utilise, je n'ai pas besoin de me soucier de désinfecter quoi que ce soit? – Michael

+0

@Michael: Sanitalizing est encore toujours une bonne idée, mais les instructions préparées sont beaucoup mieux afin d'éviter l'injection sql. – Sarfraz

+0

J'ai entendu dire que PDO s'en occupe par défaut. N'est-ce pas? – Michael

0

Étant donné que vous avez spécifiquement casté $id en nombre entier, il est sûr. Pour une chaîne (ou tout autre type de données), vous devez l'échapper avant d'exécuter la requête; jetez un oeil à PDO::quote.

0

Oui, la liaison à un nombre entier est suffisante pour empêcher l'injection SQL si le paramètre est attendu en tant qu'entier. Vous pouvez également utiliser un Automatic SQL Injection Tool pour le détecter.

0

Attention cependant, en PHP (int) convertit NULL à 0.

Par conséquent, si vous avez eu une association significative avec l'ID de 0 dans votre application, cela pourrait déclencher cette valeur sans le vouloir.

+0

'(int) convertira NULL à 0' -' $ id = str_replace ("\ 0", "", $ id) 'devrait résoudre ce problème –