views:

99

answers:

3

Certain data types, I.E. numbers or a table name cannot be added as a parameter with PDO, as it adds single quotes around them.

When I add them (the variables) manually, say something like this:

  $statement = $dbh->prepare("INSERT INTO $TABLE_NAME (id, foo, timestamp) VALUES (1234, ?, 4567890))");
  $statement->execute(Array($foo));

My question is: Does prepare() escape or properly handle ALL data within? Or just data that is bound by execute /parameter bind? my variable placing directly into the prepare() statement is rare, but I really wish to know for security when writing these.

+2  A: 

No, prepare only escapes data that uses placeholders.

jmz
+3  A: 

My question is: Does prepare() escape or properly handle ALL data within? Or just data that is binded by execute /parameter bind?

While there may be security measures to prevent unescaped data from entering the system, you can't assume anything you put into the query directly gets escaped properly.

Always bind parameters for all incoming data.

Pekka
Ouch, so this makes certain escaping impossible without a fairly heavy custom function (that mimicks mysql_real_escape_string's encoding checks).. ?
John
@John numbers aren't a problem: Their getting enclosed in quotes doesn't hurt (plus if you want to specify a numeric type, you can use [`bindParam`](http://www.php.net/manual/en/pdostatement.bindparam.php) and specify a [data type](http://www.php.net/manual/en/pdo.constants.php)). With table names, as far as I can see (and as [previously discussed](http://stackoverflow.com/questions/3665784/php-pdo-prepared-statements-dont-work-when-creating-a-table)), I think yes.
Pekka
Alright, I do not need to worry about table names so I'll just stick with bindParam. Thank you.
John
@John you HAVE to worry about table names, as well as you have to worry about bad design at all.
Col. Shrapnel
@Pekka: Treating numbers like strings will burn you if you switch to another DBMS later. Or even code against another one in another app.
R. Bemrose
but a function that mimicks mysql_real_escape_string's encoding checks is a nightmare. Again, identifier is not data. And has nothing to do with mysql_real_escape_string and do not need any encoding checks
Col. Shrapnel
I hate such "accepted" answers, which helps nothing and only leads to another stupid questions
Col. Shrapnel
@R.Bemrose good point! Duly noted. @Col there was a perfectly legitimate use case for dynamic table names in the other question. I know that building applications that run under limited circumstances is beneath you, but for some people, it is not. I agree though that writing a mock escape function is horrible.
Pekka
@Col: I mentioned it was way too late for me, I was able to indirectly clear 5-6 problems with an indirect answer.
John
A: 

No; AFAIK $-expansion is handled directly by PHP, and "foo $bar baz" is equivalent to "foo " . $bar . " baz".

tc.
What does this have to do with my question about adding them directly? The question was about if `prepare()` escaped including $bar, not that $bar was taken by PDO and escaped separately.
John
`"INSERT INTO $TABLE_NAME ..."` there you have your php variable (i.e. you've opened the door for this answer ;-)) and pdo doesn't handle this. If e.g. $TABLE_NAME contains a space pdo will not automagically quote it with grave accents.
VolkerK
Let's try to explain with a concrete example: if $TABLE_NAME is "foo default values; drop table foo; insert into bar", prepare() *just* sees "insert into foo default values; drop table foo; insert into bar ...". There's no way for prepare() to tell the difference between `$foo = abc; prepare("$foo")` and `prepare("abc")`.
tc.