What exactly is $stmt and what is it's purpose? what does it stand for..
I'm following a tutorial that is using prepared statements and looked up stmt in the manual:
http://php.net/manual/en/class.mysqli-stmt.php
and see that it is a class that "represents a prepared statement" - which i guess is a prepared sql statement that you slot a variable into. though I don't see how this id different to storing a sql statement as a string and then manipulating the string to add variables when you need?
"$stmt" obviously (I think) stands for "statement". As a variable name it's arbitrary, you can name that variable anything you want. $stmt is just rather idiomatic.
A prepared statement as such is a database feature. The database itself takes the query in two steps: first the query structure with placeholders, second the data to fill in the placeholders. The statement objects on the PHP side represent this separation and are there to give you a handle representing the prepared statement on the SQL server side.
The point of this separation is that there's no chance of having SQL injection problems due to incorrectly escaped arbitrary string values; it is also useful for performance if you reuse that prepared statement a number of times.
Working with statements is much safer than inserting variables into a plain SQL string. By using statements you prevent SQL injection. Take a look at:
How does the SQL injection from the "Bobby Tables" XKCD comic work?
&
How can I prevent SQL injection in PHP?
What exactly is $stmt and what is it's purpose?
It is a variable and stores a value
People do use it for statement - others are a bit more imaginative with variables name
Related
I have following code (simple version of it):
$query = "SELECT *
FROM text
WHERE MATCH (text) AGAINST ('".$pdo->quote($_GET["q"])."' IN BOOLEAN MODE);";
Is there any way to overcome the quote()-function and inject SQL into the query - or is quote() 100% safe?
Thank you very much!
PDO::quote() places quotes around the input string (if required) and escapes special characters within the input string, using a quoting style appropriate to the underlying driver.
So it would appear it protects against SQL injection.
Although, prepared statements guarantee SQL injection protection as we can read from PHP manual:
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.
You can read a lot more about it at http://php.net/manual/en/pdo.quote.php
I'm using PHP PDO for my queries, everywhere, but I read that in very rare cases there could still be "second order injections" where an unsafe variable is stored then executed when used in another statement.
Will prepared statements still protect against this? As long as I make sure I always use them? Or do I have to take more precautions? Am I still vulnerable to XSS attacks?
I also have a couple more questions, just out of curiosity, if you all don't mind:
Is it possible to have an SQL Injection with only alphanumeric characters, spaces, and one dash? Like select * from something where name='$some_variable'. All the examples I've seen seem to require other characters like semicolons, quotes, or double dashes.
I've read many SQL examples where the unsafe variable could be set to form another statement, eg
$foo = "foo'); INSERT INTO users (name) VALUES ('hi";
$bar = ("INSERT INTO users (name) VALUES ('$foo')");
But I just tested and mysql_query doesn't even allow multiple statements. I know you can still have injections within 1 statement, but can I confirm that you won't have problems with multiple statements in PHP?
Not to beat a dead (or is it a very alive?) horse, but...
Injection can only happen when data is read by the SQL engine as commands. In a very simple case, if you allow unescaped " characters in your data, and your data is encapsulated by " characters in SQL, they you have enabled an SQL injection attack.
The key to preventing any SQL injection is to properly validate and escape incoming data EVERY time, at the time it goes into the SQL statement. An easy way to do this is to just use prepared statements, which take care of it for you, allowing you to safely pass parameters to an SQL statement.
Each database library has it's own way of escaping or using prepared statements. In MySQL and PHP, you have mysqli_real_escape_string(), which should be used EVERY TIME PERIOD, when you are using the mysqli library.
The PDO library has it's own way, but if I recall correctly, prepared statements were a big part of PDO -- use them 100% of the time, and you will be OK in that regard.
To prevent agains XSS attacks, use HTML Purifier, and never strip_tags(), see links below for more info, PDO prepared statements should be fine for SQL Injection prevention:
http://www.reddit.com/r/PHP/comments/nj5t0/what_everyone_should_know_about_strip_tags/
http://htmlpurifier.org/
I know that this question may be closed by some of you, but my question came up from you and your answers. I am reading the past two hours questions and answers for SQL Injections and how to protect your database. The same comes to the huge amount of webpages and tutorials I saw.
I found out that half of the people claim that prepare statements do secure your db, and the other 50 claim that it is not.
On the other hand, I read that mysql_real_escape_string does the job, and other people saying that it is not.
My question is who to believe ?
In addition, is this a proper prepare statement?
$stmt = $dbh->prepare("SELECT phpro_user_id, phpro_username, phpro_password FROM phpro_users
WHERE phpro_username = :phpro_username AND phpro_password = :phpro_password");
/*** bind the parameters ***/
$stmt->bindParam(':phpro_username', $phpro_username, PDO::PARAM_STR);
$stmt->bindParam(':phpro_password', $phpro_password, PDO::PARAM_STR, 40);
/*** execute the prepared statement ***/
$stmt->execute();
Both. Prepared statements will protect you against SQL injections if, and only if, you use them in a correct manner. Just' using' prepared statements won't help if you're still interpolating variables for table/column names for example.
$stmt = "SELECT * FROM $table WHERE $column = ?"; //not good...
Prepared statements don't. Bound parameters secure the statement (not the database as a whole) so long as all your untrusted data is passed via a parameter rather than being interpolated into the statement. When people use prepared statements, they almost always use bound parameters too, so the two names are often conflated.
Prepare statement
Run statement with variables as additional arguments
mysql_real_escape_string almost always does the job, but since it adds additional steps to the process, it is more prone to human error.
Escape each variable
Concatenate variables into SQL statement
Run statement
This is a good discussion. Your question assumes there is one technique that will "secure your database". In fact, there is no single technique that is best for all cases. So you need to learn to use multiple solutions in different situations.
Escaping literal values
Parameter placeholders in prepared queries
Whitelist maps
See my presentation SQL Injection Myths and Fallacies where I give details on everything you need to know to defend against SQL injection.
I also cover SQL injection in my book, SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming.
There are certain instances when prepared statements cannot be used. For example, when you must dynamically generate the contents of an IN() clause, you cannot do WHERE col IN (?) if you have dynamically chosen the comma-separated values to go into the IN(). Also, if you need to dynamically generate the columns list in your SELECT clause, you must do it by building up the SQL string.
Bottom line is, both have their place. Prepared statements are excellent for predetermined queries, or queries that must be executed multiple times. Escaped dynamic SQL is excellent when 1) you must have maximum flexibility and 2) you don't forget to escape all your input.
I've been looking at how best to protect against sql injection in PHP/mysql beyond just using the mysqli/mysql real escape since reading this Is mysql_real_escape_string enough to Anti SQL Injection?
I have seen this very good thread How can I prevent SQL injection in PHP?
I use to do alot of ms sql server stuff on the desktop/internal tools, we always wrote stored procedures to protect against this so I read up on the equivalent in PHP/mysql using PDO http://php.net/manual/en/pdo.prepared-statements.php
In the above there is the line :
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).
I've been lead to believe that PDO do protect against sql injection attacks so can anyone provide a instance where PDO isnt sufficient from a security standpoint?
You can still get SQL injections from stored procedures which are internally using the PREPARE syntax (in MySQL) to create dynamic SQL statements.
These need to be done with extreme care, using QUOTE() as necessary.
Ideally, we should not need to use PREPARE in stored routines, but in certain cases it becomes very difficult to avoid:
Prior to MySQL 5.5, the LIMIT clause cannot use non-constant values.
Lists used in an IN() clause cannot be (sensibly) parameterised, so you need to use dynamic SQL if this pattern is used
It is sometimes desirable to use dynamically generated ORDER BY clauses.
etc
In the case where it is necessary to use PREPARE, then I would recommend, in order of preference:
If something is an INT type (etc) it is not susceptible to SQL injection, and you can place the value into the query without a problem (e.g. for LIMIT)
String values can be placed into an #variable before the EXECUTE, or passed in to the EXECUTE clause
List-values (for example for IN()) need to be checked for validity.
Finally, QUOTE() can be used to quote string values, which can be useful in some cases
It's not the structure you use (stored procedures, prepared statements etc.) that is decisive, but whether you are at any point concatenating SQL together using unchecked user input. For example, you can execute dynamic SQL from within a stored procedure, in which case the danger is still there.
The easiest way (from the injection-avoidance point of view) is to use SPs or PSs with bound-in variables: these do not need to be checked as they will be recognized as values to go within a predefined placeholder.
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.