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).
Related
I've used the following sort of code a few times in my current project to clear out some tables. Incase it's not obvious I'm using PDO.
$clearResult = $db->query('TRUNCATE TABLE table_name');
I'm currently going through and updating a few of my earlier scripts to make sure they all make use of prepared statements and are written in a way to reduce (hopefully stop) sql injection.
No, there's no user input in the actual query so there's no risk of injection.
You do have to make sure that a user isn't able to trigger the truncate though, unless they're authorized.
It's not the SQL operation that determines whether or not a prepared statement should be used. To prevent SQL Injection, a prepared statement should be used when any variable is involved in the query where bound parameters are permitted. That is not limited to just user input either, any variable at all should be a bound paremeter, regardless of where it came from.
In your example there are no variables required for the query, and so there is no security benefit of using a prepared statement.
Even if your table_name was coming from user input or a variable, a prepared statement would not be a solution because it is not possible to bind the table name.
Prepared statements would have no effect on your truncate query.
PDO prepared statements are useful when running queries with user input as they allow you to use features such as bound parameters to sanitise user input.
They are also useful for optimising queries that will run multiple times.
You might want to read up a little on prepared statements in the PHP documentation - PHP documentation for prepared statements:
Many of the more mature databases support the concept of prepared
statements. What are they? They can be thought of as a kind of
compiled template for the SQL that an application wants to run, that
can be customized using variable parameters. Prepared statements offer
two major benefits:
The query only needs to be parsed (or prepared) once, but can be
executed multiple times 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). Prepared statements are so
useful that they are the only feature that PDO will emulate for
drivers that don't support them. This ensures that an application will
be able to use the same data access paradigm regardless of the
capabilities of the database.
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()
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.
Prepared statments add a significant amount of code...yet I keep hearing mentions to use them...what value is added by going from 1 line of code to about 6? Is this simply to protect against sql injection?
Similar post here.
php.net on prepared statements here
Prepared statements offer excellent protection against SQL injection.
In addition to SQL injection protection, prepared statements offer reduced load on the database server when the same query is to executed multiple times, such as in an INSERT loop. The statement is only compiled once by the RDBMS rather than needing to be compiled each time as it would in a mysql_query() call.
Different APIs require varying amounts of code to execute a prepared statement. I find that PDO can be a little less verbose than MySQLi, if for example your situation permits the use of implicit parameter binding inside the execute() call. This only works, if all your params can be evaluated as strings though.
// PDO implicit binding example:
// Not many lines of code if the situation allows for it
$stmt = $pdo->prepare("SELECT * FROM tbl WHERE col1=? AND col2=? AND col3=?");
$stmt->execute(array($val1, $val2, $val3));
It's not fair to say that prepared statements cause 1 line of code to explode to 6. Actually, to use one you need just 2 lines: one to prepare the statement, and one to bind the parameters. Any other code you write (execute query, bind results, fetch results, etc.) would also be needed even if you didn't use prepared statements.
So in essence we are talking about what one additional line of code buys you. It buys you two things:
Protection against sql injections (which also includes protection against non-malicious malformed queries, e.g. preventing your query from breaking if an injected variable contains a single quote)
Possible performance benefits, if you end up executing the same prepared statement for different injected values.
Point #2 may not always apply, but consider that point #1 also saves you the necessary trouble of manually escaping the values to be injected in your query. This would be additional code (even if you can do it inline on the same line) that you would need to write yourself if not using prepared statements.
As I see things, we can conclude that with prepared statements you end up getting security and possibly performance for free.
Can anybody explain me in plain English what parametrized queries are and how to implement it in PHP for a MySQL database to avoid SQL injection?
The prepared statements and stored procedures section of the PHP manual, whilst it relates specifically to PDO, covers this well when it says:
They can be thought of as a kind of
compiled template for the SQL that an
application wants to run, that can be
customized using variable parameters.
Prepared statements offer two major
benefits:
The query only needs to be parsed (or
prepared) once, but can be executed
multiple times with the same or
different parameters. When the query
is prepared, the database will
analyze, compile and optimize it's
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).
If you're after specific example of how to use them, the above linked page also includes code samples.