How do you bind parameters to a query that isn't prepared? - php

I'm making a small web application that will be receiving data input by users regularly. When researching how to make sure the data input is cleansed first, and for that it would seem prepared statements are the way to go.
I've found this SO question however, and as my application (at least as far as I know) won't be doing more than one query per page request, it would seem all I really need is the binding of values to parameters in the query.
I've been looking through the PHP manual on PDO and mysqli, but I can't find any examples where values are bound to a normal query. All the examples I've found have a $stmt->prepare somewhere prior to the binding.
Is whether or not the statement is "prepared" something that's determined by the support of the database, and the prepare statement will always be in the code? Or is there a way to bind parameters directly into a $dbh->query(...)?
To explain why I'm looking to see if its possible to not use prepare, is due to this statement from the SO question I linked earlier in the post:
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)?
and this
Personally I wouldn't bother. The pseudo-prepared statements are likely to be useful for the safe variable quoting they presumably provide.

How do you bind parameters to a query that isn't prepared?
You don't. An SQL string with parameters (i.e. question marks in specific places) needs to be parsed (i.e. prepared) first before those question marks can be treated as insertion points for parameter values.
Therefore you always need to call prepare() before you can call bind().
A parameterized statement is a string that contains SQL and placeholder markers (for example question marks, but different databases use different placeholders):
$sql = "SELECT user_id FROM user WHERE user_name = ?"
Now assume there's a value you want to insert at this location:
$_POST["username"]
Preparing a statement, broadly speaking, gives the question marks their special meaning "a value can be inserted here". In other words, it creates parameters from the placeholders.
$stmt->prepare($sql)
Binding a value to a parameter sets the parameter to a specific value.
$stmt->bind_param("s", $_POST["username"])
Now the query can be executed without the SQL string and the user-supplied value ever actually coming into contact with each other. This is the important bit: SQL and parameter values are sent to the server separately. They never touch each other.
$stmt->execute();
The advantages are:
You can bind a new value to the parameter and execute the query again without having to repeat all of it (useful in a loop).
SQL injection is impossible, no matter what value $_POST["username"] contains.

You don't. Here's why:
If using $dbh->query(...)
you can just call SQL with the parameters interpolated into the SQL string. By using a query like
$dbh->query("INS INTO MY_TABLE_OF_NAMES ('$name');");
10 or so years ago, this is how most SQL was done. This is the most straightforward way of invoking the database, using the SQL interface already implemented by the RDMS, without the need for a special lower-level interface. But people discovered that this was dangerous because of something called SQL injection.
http://en.wikipedia.org/wiki/Sql_injection
The simplest and most common example goes something like this. Suppose you had an SQL call on your web page that would run:
INS INTO MY_TABLE_OF_NAMES VALUE ('$name');
But then someone would come to your site and enter there name as bob'); DROP TABLE MY_TABLE_OF_NAMES;
Suddenly your interpolated SQL statement becomes
INS INTO MY_TABLE_OF_NAMES VALUE ('bob'); DROP TABLE MY_TABLE_OF_NAMES; );
Which would subsequently insert bob into your database, delete all of your names, and throw an error for the trailing ); when your website ran it.
So, prepared statements were invented. Instead of interpolating strings directly into your SQL, it will use ? characters to denote dynamic values, and a bind function is used to insert the string safely. This way malevolent input will never be interpreted as SQL code by your database engine and your site can't be tricked into doing things it doesn't want to do. The prepare command takes an SQL string takes a bit of SQL and semi-compiles it into a lower-level database language leaving spaces open of dynamic strings wherever a ? is used. Bind then fills one of those open spaces with a piece of data, encoded to escaped ASCII, so that it cannot be misinterpreted as SQL code. Once all of those ?s are filled, the SQL is ready to be sent to the RDMS to be run.
So to answer your question, you will never bind a parameter to a simple query. If you want dynamic variables in a simple query you will just interpolate them into the SQL string. But this is dangerous. Prepared statements allow you to precompile an SQL statement then safely bind dynamic parameters to it to create safe dynamic SQL. Binding to SQL is purely a construct of prepared statements.

In order to use bound parameters, you have to use prepared statements. This is just the way things are currently implemented in pdo and mysqli. I'm not sure if certain database products support some type of communication protocol where parametrized sql(sql text which uses placeholders) is sent along with the parameter values without having to first do an explicit prepare call, but pdo and mysqli don't expose this functionality if it's available. It would sure be a welcome feature to web apps.
With pdo, yes, whether or not the sql statement actually gets prepared when you call $dbh->prepare($sql) does depend on database support. pdo will emulate prepared statements when the database doesn't support them, or it can always emulate them if its configured to do so. In fact, pdo emulates prepared statements for the mysql driver by default, and has done so by default for a very long time. It emulates them by creating dynamic sql, quoting the values, just like you would. In this case, the sql(with the final values embedded into the text) is sent to the database when you call $stmt->execute(). Yes, sql injection is possible here under certain scenarios.

Related

Should I use bindParam(), bindValue(), or execute() for PDO prepared statements

I read this question (Should I use bindValue() or execute(array()) to avoid SQL injection?) and found that both execute( array() ) and bindParam() both prevent SQL injections when working with PDO and prepared statements.
However I also recall reading somewhere that execute() automatically treats every variable as a string, regardless if it's an integer. My question is surely this is a security issue for anything but string variables?
For example, if I was to get the id of a user where it equals 1 via a prepared query, however the parameters passed through execute will be treated as a string not an integer.
Obviously this script will have no method of user input, and will only support user input such as updating a profile, post, etc.
I am learning PDO so I'm trying to fully understand how to write secure PDO queries (or even better, functions) that are preventing/protecting against SQL injection and other security flaws.
Thanks
Security wise, there is not a single problem with sending parameters into execute(). So, your concern is superfluous. Given strings are treated safely AND we are sending all our parameters as strings, we can logically conclude that all parameters are treated safely (note that I don't blame your question. It's always better to ask than sorry. I am just making things straight).
The only possible issue with treating all parameters as strings is on the database server side. Yet most database servers allow loose typing in SQL, means any data literal will be recognized and treated properly, despite being sent as a string. There are only few edge cases when it won't work. Here is an excerpt from my PDO tutorial on the matter:
However, sometimes it's better to set the data type explicitly.
Possible cases are:
LIMIT clause in emulation mode or any other SQL clause that just cannot accept a string operand.
complex queries with non-trivial query plan that can be affected by a wrong operand type
peculiar column types, like BIGINT or BOOLEAN that require an operand of exact type to be bound (note that in order to bind a BIGINT
value with PDO::PARAM_INT you need a mysqlnd-based
installation).
As a conclusion, given you already turned emulation off, you can use the execute() method virtually all the time.

Can someone clearly explain why mysqli_prepare()/bind_param() is better than real_escape_string()? [duplicate]

This question already has answers here:
Why is using a mysql prepared statement more secure than using the common escape functions?
(7 answers)
Closed 9 years ago.
Okay, I still don't really get it. I keep reading that in order to properly escape your MySQL queries, you need to use mysqli_prepare() and mysqli_bind_param().
I tried using this setup and, quite frankly, it's a little clunkier. I'm stuck passing variables by reference when I don't need to ever reference them again, and it's just more lines of code to accomplish the same task.
I guess I just don't get what the difference is between:
<?php
$sql = new \MySQLi(...);
$result = $sql->query('
UPDATE `table`
SET
`field` = "'.$sql->real_escape_string($_REQUEST[$field]).'";
');
?>
and
<?php
$sql = new \MySQLi(...);
$stmt = $sql->prepare('
UPDATE `table`
SET
`field` = ?;
');
$value = $_REQUEST[$field];
$stmt->bind_param('s', $value);
$stmt->execute();
$result = $stmt->get_result();
unset($value);
?>
other than more code.
I mean, did they implement this so that people wouldn't forget to escape values before sending them in a query? Or is it somehow faster?
Or should I use this method when I intend to use the same query repeatedly (since a mysqli_stmt can be reused) and use the traditional method in other cases?
What you are reading, that you need to use mysqli_prepare() and mysqli_bind_param() functions to "properly escape your MySQL queries" is wrong.
It is true that if you use mysqli_prepare() and mysqli_bind_param(), you needn't (and shouldn't) "escape" the values supplied as bind parameters. So, in that sense, there's some truth in what you are reading.
It's only when unsafe variables are included in the SQL text (the actual text of the query) that you need to "properly escape" the variables, usually by wrapping the variables in mysqli_real_escape_string() function calls.
(We note that it's possible to make of use of prepared statements and still include un-escaped variables in the SQL text, rather than passing the variable values as bind_parameters. That does sort of defeats the purpose of using prepared statements, but the point is, either way, you can write code that is vulnerable.
MySQL now supports "server side" prepared statements (if the option is enabled in the connection), and that's a performance optimization (in some cases) of repeated executions of identical SQL text. (This has been long supported in other databases, such as Oracle, where making use of prepared statements has been a familiar pattern for, like, since forever.)
Q: Did they implement [prepared statements] so that people wouldn't forget to escape values before sending them in a query?
A: Based on the number of examples of code vulnerable to SQL Injection when not using prepared statements, despite the documentation regarding mysql_real_escape_string() function, you'd think that certainly would be sufficient reason.
I think one big benefit is that when we're reading code, we can see a SQL statement as a single string literal, rather than a concatenation of a bunch of variables, with quotes and dots and calls to mysql_real_escape_string, which isn't too bad with a simple query, but with a more complex query, it is just overly cumbersome. The use of the ? placeholder makes for a more understandable SQL statement,... true, I need to look at other lines of code to figure out what value is getting stuffed there. (I think the Oracle style named parameters :fee, :fi, :fo, :fum is preferable to the positional ?, ?, ?, ? notation.) But having STATIC SQL text is what is really the benefit.
Q: Or is it somehow faster?
As I mentioned before, the use of server side prepared statements can be and advantage in terms of performance. It's not always the case that it's faster, but for repeated execution of the same statement, where the only difference is literal values (as in repeated inserts), it can provide a performance boost.
Q: Or should I use this method when I intend to use the same query repeatedly (since a mysqli_stmt can be reused) and use the traditional method in other cases?
That's up to you. My preference is for using STATIC SQL text. But this really comes from a long history of using Oracle, and using the same pattern with MySQL fits naturally. (Albeit, from Perl using the DBI interface, and Java using JDBC and MyBATIS, or other ORMs (Hibernate, Glassfish JPA, et al.)
Following the same pattern just feels natural in PHP; the introduction of mysqli_ and PDO are a welcome relief from the arcane (and abused) mysql_ interface.
Good code can be written following either pattern. But I challenge you to think ahead, about more complex SQL statements, and whether the choice to use mysqli_real_escape_string() and concatenating together a dynamic string to be executed, rather than using static SQL text and bind parameters, might make reading, and deciphering, the actual SQL being executed more complicated for the soul that finds themselves maintaining code they didn't write.
I think studies have shown that code is read ten times more than it is written, which is why we strive to produce readable, understandable code, even if that means more lines of code. (When each statement is doing a single identifiable thing, that's usually easier for me to understand than reading a jumble of concatenated function calls in one complicated statement.
I think it's less a question of the latter method being more secure per se than encouraging separation of logic. With prepared statements the SQL query is independent of the values we use. This means, for example, when we go back and change our query we don't have to concatenate a bunch of different values to a string, and maybe risk forgetting to escape our input. Makes for more maintainable code!
There are a couple main benefits I found that were well written:
The overhead of compiling and optimizing the statement is incurred
only once, although the statement is executed multiple times. Not
all optimization can be performed at the time the prepared statement
is compiled, for two reasons: the best plan may depend on the
specific values of the parameters, and the best plan may change as
tables and indexes change over time.
Prepared statements are resilient against SQL injection, because
parameter values, which are transmitted later using a different
protocol, need not be correctly escaped. If the original statement
template is not derived from external input, SQL injection cannot
occur.
On the other hand, if a query is executed only once, server-side prepared statements can be slower because of the additional round-trip to the server. Implementation limitations may also lead to performance penalties: some versions of MySQL did not cache results of prepared queries, and some DBMSs such as PostgreSQL do not perform additional query optimization during execution.
Source
I would like to add that mysqli_bind_param() has been removed as of PHP 5.4.0. You should use mysqli_stmt_bind_param()

Parameterized PDO statements: should trusted, constant values be parameterized?

SELECT name FROM customers WHERE location = ? AND active = '1'
In this query, the value for location would come from an untrusted source, but the value for active is going to always be = 1. I'm using PDO for php/mysql.
Should I also parameterize the value for active?
If active wasn't a constant but came from a changing and trusted source, should I still parameterize? (ie. for caching benefits?)
No, there is no benefit to parameterizing constant values.
The purpose of parameterizing is to allow application data to be combined with SQL expressions safely and repeatedly. The safely part is to prevent SQL injection. The repeatedly part is so you can execute a prepared query again with different values, possibly relieving the RDBMS from having to re-parse and re-optimize the query.
Neither of these is an issue if you always use the same constant value in your query. You are not at risk of SQL injection from a hardcoded value, and you can re-execute the query if you need to, without re-parsing.
There's no caching of parameters going on. If anything, using prepared statements makes it harder for MySQL to cache the results (i.e. the query cache has limitation on caching results from prepared statements). But once you use prepared statements, it doesn't matter if it has one parameter versus two or more.
I do wonder why you put the integer in quotes. I see that a lot, but I have no idea how that got started or who thought it was necessary.

PDO insert statement and comma separator

I have:
INSERT INTO post(title,message) VALUES (:title,:message)
where :message value has some random text with symbols (including comma).
As the comma symbol is the separator between components of the statement:
How can i escape :message value to keep its included commas in the string context and not be interpreted as the separator?
You don't need to. The whole point of using prepared statements, as you are with PDO, is that the structure of the query is sent separately from the data. This means that characters in the data are never confused for parts of the structure of the query.
You've done all you need to do to make the query safe in this regard.
Prepared statements my friend.
This is what php.net has to say;
The query only needs to be parsed (or prepared) once, but can be executed multiple time with the same or different parameters. When
the query is prepared, the database will analyze, compile and optimize
its plan for executing the query. For complex queries this process can
take up enough time that it will noticeably slow down an application
if there is a need to repeat the same query many times with different
parameters. By using a prepared statement the application avoids
repeating the analyze/compile/optimize cycle. This means that prepared
statements use fewer resources and thus run faster.
The parameters to prepared statements don't need to be quoted; the driver automatically handles this. If an application exclusively uses
prepared statements, the developer can be sure that no SQL injection
will occur (however, if other portions of the query are being built up
with unescaped input, SQL injection is still possible).

mysqli prepared statements and mysqli_real_escape_string [duplicate]

This question already has an answer here:
Is mysql_real_escape_string() necessary when using prepared statements?
(1 answer)
Closed 3 months ago.
I'm currently using the mysqli php extension.
Traditionally I have used mysqli_real_escape_string to escape user input. However I am looking at changing over the code (hopefully in as few steps as possible) to use prepared statements.
I want to be clear on this - provided I use prepared statements to bind all of my variables, can I be confident that sql injection is impossible? (And dispense completely with mysqli_real_escape_string?)
Thanks
If you correctly bind all your variables you can dramatically reduce the risk of SQL injection. It is still possible to get an SQL injection if you create SQL dynamically for example:
'SELECT * FROM ' . $tablename . ' WHERE id = ?'
But if you avoid things like this it is unlikely you will have problems.
Speaking of security, there is no difference between both methods, if you correctly bind or format your variables.
Binding is just simpler, because it can be used just for any case, while escaping can't (so, you have to cast some variables instead of escaping/quoting).
Also, bear in mind that no binding nor escaping can make identifier safe. So, if you have to use a field name or operator in your query, you have to use a value, hardcoded in your script.
Here's my high-level view on the topic.
When using dynamic SQL strings, you are relying on the escaping function working correctly. Unfortunately, this is not always the case, as can be seen in this (admittedly old) example:
http://dev.mysql.com/doc/refman/5.0/en/news-5-0-22.html
Once your data values have been escaped, the SQL string has to be parsed and compiled by the database server. If the escaping function has not done its job properly, or a clever new SQL injection attack has been discovered, there is a chance that the server will mistake data for SQL statements.
If you use prepared statements with parameters, the statement is first parsed and compiled. The data values are combined with the compiled statement when it is executed. This separates the SQL logic from the data values - the opportunity to confuse the two should never occur.
So, yes, you can dispense with mysqli_real_escape_string, but I would not go so far as to say that using prepared statements with parameters makes SQL injection impossible. It makes it significantly harder, but as with the mysqli_real_escape_string bug, I guess there's always the chance that a yet to be discovered (or newly created) bug will make the seemingly impossible, possible.

Categories