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
Related
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
I've used a mysql_real_escape_string till now but it seems that It's not working at GoDaddy Hostings. How should I clean up the string for a database? I've found a PDO::quote but the manual says
"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."
Is that means that prepare + bind_params are doing the same thing?
Sorry for my English.
Unfortunately, PHP manual often being unclear, wrong or deceiving.
Prepared statements with bound parameters are
more portable (not true)
more convenient (that's the only true statement),
immune to SQL injection (quote() makes things immune as well),
often much faster to execute (a mere lie)
So, you can use either way, but prepared statements let you have the shorter code:
$id = $pdo->quote($id);
$name = $pdo->quote($name);
$stm = $pdo->query("SELECT * FROM t WHERE id=$id AND name=$name");
vs.
$stm = $pdo->query("SELECT * FROM t WHERE id=? AND name=?");
$stm->execute(array($id,$name));
Though that's not the only reason: please refer to some explanations I made on Why one should use prepared statements
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'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.
I'm using prepared statements and MySQLi with my queries to protect against injection attacks. Would prepared statements remove the need for mysql_real_escape_string entirely? Is there anything else I should consider when securing my site?
As long as you're using the prepared statements correctly they will. You have to make sure you're binding all the external variables and not putting them directly in the query.
For example
$stmt = $mysqli->prepare("SELECT District FROM City WHERE Name=" . $name);
This statement is being prepared, but it doesn't use one of the bind methods so it does no good. It is still vulnerable to SQL injection.
To fix that make sure to bind everything...
$stmt = $mysqli->prepare("SELECT District FROM City WHERE Name=?")) {
$stmt->bind_param("s", $city);
I'm using prepared statements and MySQLi with my queries to protect against injection attacks.
Don't do it. Don't use prepared statements to protect from anything. It is not what prepared statements are for. It is just to make your queries syntactically correct. And, as a side effect, a syntactically correct query is invulnerable to any attack too.
So, just use it to put data into query.
Would prepared statements remove the need for mysql_real_escape_string entirely?
That's wrong from the mysql_real_escape_string side. this function do not protect you from anything. If you just apply this function to your data, it wouldn't make it "safe". this function works for the quoted strings only.
While yes, using prepared statements makes this function obsolete, as well as other plain SQL assembling rules. It actually does the job you think mysql_real_escape_string do. It does actually make any data safe (for SQL).
Is there anything else I should consider when securing my site?
Sure.
Not to talk of whole city - it's another and way too broad question, but of SQL query again:
Prepared statements makes only data safe.
Thus, you have to take care of dynamical non-data parts of the query, such as field names, operators, etc. Prepared statements won't help you with them.