views:

122

answers:

5

I am using PDO to talk to my database, and I wonder if casting a type like this

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

is sufficient to prevent sql injection? In this case $id is always an integer.

I also wonder what would be a good way to prevent an injection in this kind of statement if the variable was a string.

+4  A: 

Yes. Casting to int prevents all the nasty SQL injection possibilities.

If the variable were a string, you should use prepared statements to pass it.

$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();
Scytale
A: 

You must escape table and field names in query:

$dbh->query("SELECT * FROM `recipes` WHERE `id=`'".(int)$id."'");
Alexander.Plutov
two mistakes in attempt to improve... :-O
Col. Shrapnel
It's not a *must* unless it's a keyword, but yes, it is good practice to do it anyway.
casablanca
+2  A: 

Since you are already using PDO, a better approach will be to use:

This is much better:

$dbh->prepare("SELECT * FROM recipes WHERE id = ?");
$dbh->bindParam(1, (int) $id);
// more code.....
Sarfraz
So if I use them, I do not need to worry about sanitizing anything?
Michael
@Michael: Sanitalizing is still always a good idea but prepared statements are far more better in order to prevent sql injection.
Sarfraz
@Sarfraz, I heard that PDO takes care of it by default. Isn't that so?
Michael
@Michael: unless you use prepared statements out of the PDO.
Sarfraz
A: 

Since you specifically cast $id to an integer, it is safe. For a string (or any other data type) you need to escape it before executing the query; have a look at PDO::quote.

casablanca
A: 

Yes, bind to a integer is enough to prevent SQL Injection if the parameter is expected as a integer.

You can also use an Automatic SQL Injection Tool to detect it.

Yale