I tried Google to find any disadvantage but did not find any !
I'll be glad if anyone share some thing on this topic !
Advantage/ disadvantage of PDO and Prepared Statement
Edit 2 :
I think everyone want to say Prepared Statement is better than PDO ?
Am i right ?
The major disadvantage to PDO will be it takes a bit more querying time (I cannot "prove" this so don't take it as fact just what I have noticed / read), which is well less then a second. But if you need that extra less then a second mysqli offers prepared statements like PDO and I believe works a bit quicker given it is set for one database and not many.
It is more code, but as nikic stated, use a wrapper class to setup your statements so your code can look something like:
$db->fetchAll('SELECT * FROM table WHERE name = ?', $name);
Where fetchAll is a custom function you write to handle the binding of the params etc.
Which would I use? mysqli or PDO (PDO due to its versatility personally). MySQL (not mysqli) is kind of outdated, and in the end you could be writing a lot more code using MySQL in that you always have to filter the input (as in escape to prevent SQL injections, it will not validate what should be put in there) before putting it into the database. Using prepared statements, the filtering is all done for you and the chance for an Injection is very low as long as it is used properly.
The real big advantage of prepared statements is that the parameters passed in to the ? are checked for validity. So SQL injection attacks are harder than if you create your sql something like this
$SQL = "INSERT INTO table VALUES('" & $stringfromForm & "');";
as if somecone could set up enter the following into the form
x'); INSERT INTO someothertable VALUES ('rubbish
then you could be in trouble
Related
I'm re-engineering a PHP-driven web site which uses a minimal database. The original version used "pseudo-prepared-statements" (PHP functions which did quoting and parameter replacement) to prevent injection attacks and to separate database logic from page logic.
It seemed natural to replace these ad-hoc functions with an object which uses PDO and real prepared statements, but after doing my reading on them, I'm not so sure. PDO still seems like a great idea, but one of the primary selling points of prepared statements is being able to reuse them… which I never will. Here's my setup:
The statements are all trivially simple. Most are in the form SELECT foo,bar FROM baz WHERE quux = ? ORDER BY bar LIMIT 1. The most complex statement in the lot is simply three such selects joined together with UNION ALLs.
Each page hit executes at most one statement and executes it only once.
I'm in a hosted environment and therefore leery of slamming their servers by doing any "stress tests" personally.
Given that using prepared statements will, at minimum, double the number of database round-trips I'm making, am I better off avoiding them? Can I use PDO::MYSQL_ATTR_DIRECT_QUERY to avoid the overhead of multiple database trips while retaining the benefit of parametrization and injection defense? Or do the binary calls used by the prepared statement API perform well enough compared to executing non-prepared queries that I shouldn't worry about it?
EDIT:
Thanks for all the good advice, folks. This is one where I wish I could mark more than one answer as "accepted" — lots of different perspectives. Ultimately, though, I have to give rick his due… without his answer I would have blissfully gone off and done the completely Wrong Thing even after following everyone's advice. :-)
Emulated prepared statements it is!
Today's rule of software engineering: if it isn't going to do anything for you, don't use it.
I think you want PDO::ATTR_EMULATE_PREPARES. That turns off native database prepared statements, but still allows query bindings to prevent sql injection and keep your sql tidy. From what I understand, PDO::MYSQL_ATTR_DIRECT_QUERY turns off query bindings completely.
When not to use prepared statements? When you're only going to be running the statement once before the db connection goes away.
When not to use bound query parameters (which is really what most people use prepared statements to get)? I'm inclined to say "never" and I'd really like to say "never", but the reality is that most databases and some db abstraction layers have certain circumstances under which they won't allow you to bind parameters, so you're forced to not use them in those cases. Any other time, though, it will make your life simpler and your code more secure to use them.
I'm not familiar with PDO, but I'd bet it provides a mechanism for running parametrized queries with the values given in the same function call if you don't want to prepare, then run as a separate step. (e.g., Something like run_query("SELECT * FROM users WHERE id = ?", 1) or similar.)
Also, if you look under the hood, most db abstraction layers will prepare the query, then run it, even if you just tell it to execute a static SQL statement. So you're probably not saving a trip to the db by avoiding explicit prepares anyhow.
Prepared statements are being used by thousands of people and are therefore well-tested (and thus one can infer they are reasonably secure). Your custom solution is only used by you.
The chance that your custom solution is insecure is pretty high. Use prepared statements. You have to maintain less code that way.
The benefits of prepared statements are as follows:
each query is only compiled once
mysql will use a more efficient transport format to send data to the server
However, prepared statements only persist per connection. Unless you're using connection pooling, there would be no benefit if you're only doing one statement per page. Trivially simple queries would not benefit from the more efficient transport format, either.
Personally I wouldn't bother. The pseudo-prepared statements are likely to be useful for the safe variable quoting they presumably provide.
Honestly, I don't think you should worry about it. However, I remember that a number of PHP data access frameworks supported prepare statement modes and non-prepare statement modes. If I remember correctly, PEAR:DB did back in the day.
I have ran into the same issue as you and I had my own reservations, so instead of using PDO I ended up writing my own light-weight database layer that supported prepares and standard statements and performed correct escaping (sql-injection prevention) in both cases. One of my other gripes with prepares is that sometimes it is more efficient to append some non-escapable input to a statement like ... WHERE id IN (1, 2, 3...).
I don't know enough about PDO to tell you what other options you have using it. However, I do know that PHP has escaping functions available for all database vendors it supports and you could roll your own little layer on top of any data access layer you are stuck with.
I am new to the CodeIgniter framework for php and was looking at the PDO database driver with Version 2.1.0. I noticed it uses the PDO 'query' function and not 'prepare' and 'bindParam'/'bindValue'.
Doesn't this completely miss the point of using PDO in the first place and in fact make it less protected from sql injection than using the normal mysql driver they provide. It doesn't seem to be escaping queries like it does with the other provided drivers? Or am I completely misinterpreting something?
EDIT: It looks as if CodeIgniter may in fact be using PDO::quote to sanitize. But even the php documentation says this is not recommended as it is less secure and seemed to miss the point of PDO in the first place
I've not used CodeIgniter so I actually had to do a little research on this. As it turns out, CodeIgniter does offer a semblance of parameterized queries called Query Bindings.
It works like this:
$sql = "SELECT * FROM some_table WHERE id = ? AND status = ? AND author = ?";
$this->db->query($sql, array(3, 'live', 'Rick'));
According to the documentation:
The secondary benefit of using binds is that the values are automatically escaped, producing safer queries. You don't have to remember to manually escape data; the engine does it automatically for you.
It is odd to me though that it abstracts the prepared statements functionality. I figured that was pretty much cut and dry. Heh :/
I'm looking at the source code, and I see escape_str calls quote, and DB_driver->escape calls escape_str. I haven't quite tracked down the overall structure. So I don't know for sure if escape itself is called where it should be.
However, PDO::quote is safe if used correctly. Prepared statements are easier for application programming, but PDO::quote may be a better choice for libraries that provide their own abstraction.
I dunno CI but there is a simple rule to remember:
Despite of the common [weird] belief,
Escaping alone does nothing good.
As a matter of fact, it should be always escaping+quoting.
If we don't quote escaped data, we get no good from escaping.
So, I suppose that CI does both.
If so - it should be safe.
The only consequence I can think of is LIMIT parameters.
If you pass them as variables of string type, CI query might throw an error, like PDO in compatibility mode does. I'd be grateful if you test this behavior and post the result.
That actually sounds right to me. The docs for pdo::query() say "data inside the query should be properly escaped." If you follow the link to pdo::quote(), there's a prominent warning:
If you are using this function to build SQL statements, you are strongly recommended to use PDO::prepare() to prepare SQL statements with bound parameters instead of using PDO::quote() to interpolate user input into an SQL statement. Prepared statements with bound parameters are not only more portable, more convenient, immune to SQL injection, but are often much faster to execute than interpolated queries, as both the server and client side can cache a compiled form of the query.
I can't offer any insight into why codeigniter is using query() instead of prepare(), though.
To use pdo with prepare statement, you need to do a little modification.
http://christopherickes.com/web-app-development/using-pdo-in-codeigniter/
then, you can use prepare statement.
I inherited a moderately large sized code base that makes extensive use of mysql_fetch_assoc and mysql_fetch_object, and doesn't have any security precautions preventing SQL injection. I decided that this was a Very Bad ThingTM that needed fixing.
Initially, I intended on moving to mysqli prepare/bind_param/execute statements to handle DB queries. However, the following does not work:
$stmt = $GLOBALS['db']->prepare('SELECT * FROM Users WHERE Username=?');
$stmt->bind_param('s', $username);
$stmt->execute();
// Somehow retrieve the fetched row as an object (Doesn't work!)
return $stmt->fetch_assoc();
Question 1: Is there a way to use fetch_assoc or fetch_object using prepare/bind? I can refactor all the code, but it would be messy and take a very long time.
Question 2: If it is not possible to do this, is it just as effective from a security standpoint to use mysqli_query(), provided all inputs are properly escaped via mysql_real_escape_string()? Do you have any other suggestions?
$row = $stmt->fetch(PDO::FETCH_ASSOC) Ref: http://php.net/manual/en/pdostatement.fetch.php
You can use mysqli if you want. As long as you use the real_escape_string functions on ALL user data (including your own) that's going into SQL statements, then it's no less secure than using prepared statements - it's just much easier to miss a post and leave a hole open.
Replacing raw mysql with raw mysli makes very little sense.
in fact, all those doleful repetitive prepare/bind/execute/fetch being as ugly as mysql_query/fetch.
If you going to refactor your code anyway, you have to develop some library function, which will take a query and it's prameters as arguments and return an array of data, doing all the fetching inside.
as for the escaping all inputs via mysql_real_escape_string(), it is going to be an equivalent of magic quotes, which, at last, been acknowledged as a bad practice.
in fact, mysql_real_escape_string() doesnt make any data safe. it has nothing to do with safety at all. it's merely a formatting routine, and works only for strings. But there are other types to insert into query. For the detailed explanations refer to my prefious answer, How to include a PHP variable inside a MySQL insert statement
PDO and prepared statements are still kind of confusing to me, no matter how much I read about them so far. So I know they are more "secure" but is it really that important? I mean I can get the same end result using basic mysql with mysql_real_escape_string() and htmlspecialchars() right?
You could, but PDO and prepared statements are the absolute safest. Could you do it by hand and use the mysql_real_escape_string() function? Sure. In fact, your output might look identical. But in the end, the code that PDO would require would be a hell of a lot shorter than the code if you had done it manually.
Also, if you aren't using prepared statements, you run the risk of human error: say you forget to escape a value or sanitize an input. Mixed in with all of your other code, the one line that isn't properly sanitizing could crop up to be a nightmare down the road.
Hope this helps!
I really like the PDO interface. Once you get used to it, it's a lot cleaner than the mysql_* function style. It took me a while to figure it out, too, but it's worth it.
The part that I found confusing was remembering what methods belong to the PDO DB connection object itself, and which are part of the statement objects.
With certain actions, you'll get a performance benefit from repeating prepared statements, too. For instance, if you're doing a bunch of inserts in a loop, you can prepare the statement, and then bind new data in the loop each time before inserting.
The security is much better too, in that you are relying on a well tested library to escape your data on each insert. It's like cryptography - why do it yourself, when it's something this important? There's no reason to give yourself a chance to get it wrong (i.e., accidentally miss escaping something inserted into a query).
I recommend this guide to PDO, from the author who wrote this excellent giant book on Mysql.
I like to use the positional parameter style, and then you just make an array of the data and pass it in. My queries look like
$pdo_db=pdo_connect('cow_db');
$sql='select this,that,count(those) as snout from lovely_table where name=? and horses=?';
$data=array($username,$horse_count);
$query_stmt=$pdo_db->prepare($sql);
$result_handle=$query_stmt->execute($data);
//then I have a function to load data from the result handle
$info=load_array($result_handle);
You could make functions like this to work with the standard php mysql interface, but why not just use PDO?
I agree with others who say using prepared queries is generally better than using escaping functions. It's easier to use correctly, and there's no way that parameter values can introduce SQL injection problems, since the value are sent to the RDBMS server separately from the SQL query.
However, using parameters is useful only when the dynamic parts of your SQL query is a parameter in lieu of a literal value in an expression. You can't use a query parameter in place of a table name, column name, an SQL expression, or a list of values (e.g. arguments of an IN( ) predicate).
Prepared queries also have better performance than non-prepared queries (at least in MySQL). Most people say the opposite, but the well-respected mysqlperformanceblog.com did the testing:
http://www.mysqlperformanceblog.com/2006/08/02/mysql-prepared-statements/
As long as you sanitize data appropriately for your queries then you don't have to use PDO/prepared statements. Though, I would personally recommend using PDO/prepared statements simply because they do both make development/debugging easier and prepared statements prevent incorrect data types from even getting in to a query.
If you want to learn more about how to create a simple prepared statement look in to the function sprintf. You simply replace any variable strings, integers, etc with a type specifier (in this case %s and %d respectively).
So for example in the following query, I know that id is going to be an integer (it will be numerical) and name will be a string (alphanumeric).
$username = 'Simon';
$id = 3;
$query = "SELECT FROM `users` WHERE `id` = {$id} AND `name` = '{$username}'";
If I'm getting either of this variables from an un-trusted source (such as a POST/GET) then I can make sure they are the correct data types by replacing the final line (the $query set) with a sprintf call like this:
$username = 'Simon';
$id = 3;
$query = sprintf( "SELECT FROM `users` WHERE `id` = %d AND `name` = '%s'", $id, $username );
sprintf will simply not let me use a string for the $id or an integer for the $name when it is called which ensures the correct types of data are given (this gives me that little extra bit of security). IF incorrect data types ARE given then I believe it'll cast the variables to the requested type.
To read more about sprintf visit here: http://php.net/sprintf
I hope this explains enough (it's my first answer) :).
you could try zend_db which uses pdo under the hood. (mdb2 is another option you can use.)
PHP lets you do anything you want, and it just so happens PDO does what "you want" with a lot less code. :)
I'm re-engineering a PHP-driven web site which uses a minimal database. The original version used "pseudo-prepared-statements" (PHP functions which did quoting and parameter replacement) to prevent injection attacks and to separate database logic from page logic.
It seemed natural to replace these ad-hoc functions with an object which uses PDO and real prepared statements, but after doing my reading on them, I'm not so sure. PDO still seems like a great idea, but one of the primary selling points of prepared statements is being able to reuse them… which I never will. Here's my setup:
The statements are all trivially simple. Most are in the form SELECT foo,bar FROM baz WHERE quux = ? ORDER BY bar LIMIT 1. The most complex statement in the lot is simply three such selects joined together with UNION ALLs.
Each page hit executes at most one statement and executes it only once.
I'm in a hosted environment and therefore leery of slamming their servers by doing any "stress tests" personally.
Given that using prepared statements will, at minimum, double the number of database round-trips I'm making, am I better off avoiding them? Can I use PDO::MYSQL_ATTR_DIRECT_QUERY to avoid the overhead of multiple database trips while retaining the benefit of parametrization and injection defense? Or do the binary calls used by the prepared statement API perform well enough compared to executing non-prepared queries that I shouldn't worry about it?
EDIT:
Thanks for all the good advice, folks. This is one where I wish I could mark more than one answer as "accepted" — lots of different perspectives. Ultimately, though, I have to give rick his due… without his answer I would have blissfully gone off and done the completely Wrong Thing even after following everyone's advice. :-)
Emulated prepared statements it is!
Today's rule of software engineering: if it isn't going to do anything for you, don't use it.
I think you want PDO::ATTR_EMULATE_PREPARES. That turns off native database prepared statements, but still allows query bindings to prevent sql injection and keep your sql tidy. From what I understand, PDO::MYSQL_ATTR_DIRECT_QUERY turns off query bindings completely.
When not to use prepared statements? When you're only going to be running the statement once before the db connection goes away.
When not to use bound query parameters (which is really what most people use prepared statements to get)? I'm inclined to say "never" and I'd really like to say "never", but the reality is that most databases and some db abstraction layers have certain circumstances under which they won't allow you to bind parameters, so you're forced to not use them in those cases. Any other time, though, it will make your life simpler and your code more secure to use them.
I'm not familiar with PDO, but I'd bet it provides a mechanism for running parametrized queries with the values given in the same function call if you don't want to prepare, then run as a separate step. (e.g., Something like run_query("SELECT * FROM users WHERE id = ?", 1) or similar.)
Also, if you look under the hood, most db abstraction layers will prepare the query, then run it, even if you just tell it to execute a static SQL statement. So you're probably not saving a trip to the db by avoiding explicit prepares anyhow.
Prepared statements are being used by thousands of people and are therefore well-tested (and thus one can infer they are reasonably secure). Your custom solution is only used by you.
The chance that your custom solution is insecure is pretty high. Use prepared statements. You have to maintain less code that way.
The benefits of prepared statements are as follows:
each query is only compiled once
mysql will use a more efficient transport format to send data to the server
However, prepared statements only persist per connection. Unless you're using connection pooling, there would be no benefit if you're only doing one statement per page. Trivially simple queries would not benefit from the more efficient transport format, either.
Personally I wouldn't bother. The pseudo-prepared statements are likely to be useful for the safe variable quoting they presumably provide.
Honestly, I don't think you should worry about it. However, I remember that a number of PHP data access frameworks supported prepare statement modes and non-prepare statement modes. If I remember correctly, PEAR:DB did back in the day.
I have ran into the same issue as you and I had my own reservations, so instead of using PDO I ended up writing my own light-weight database layer that supported prepares and standard statements and performed correct escaping (sql-injection prevention) in both cases. One of my other gripes with prepares is that sometimes it is more efficient to append some non-escapable input to a statement like ... WHERE id IN (1, 2, 3...).
I don't know enough about PDO to tell you what other options you have using it. However, I do know that PHP has escaping functions available for all database vendors it supports and you could roll your own little layer on top of any data access layer you are stuck with.