I've seen lots of articles and questions about mysqli, and all of them claim that it protects against sql injections. But is it fool proof, or is there still some way to get around it. I'm not interested in cross site scripting or phishing attacks, only sql injections.
What I should have said to begin with is that I am using prepared statements. That is what I meant with mysqli. If I use prepared statements without any string concatenation, then is it foolproof?
But is it fool proof, or is there still some way to get around it.
No, you have to know what you're doing. If you use bound parameters (A feature that MySqli comes with), you are completely safe from injection type attacks from this attack vector. This doesn't prevent you - the programmer - from embedding strings directly, and thereby enabling injection attacks. You have to use the feature as intended.
Re: Edit
What I should have said to begin with is that I am using prepared statements. That is what I meant with mysqli. If I use prepared statements without any string concatenation, then is it foolproof?
Foolproof is still such a dangerous word. But you are safe from injection attacks for the variables that are bound through prepared statements. This is because bound parameters are transmitted separately from the SQL query. With the "traditional" embed-string approach, the database server needs to parse the input and there are lots of edge cases in that (Charsets etc.). When the data and the query are sent separate, there is no actual parsing going on (At least not parsing of the variable data).
It doesn't protect from sql injections any better than the old mysql module, just makes doing it easier for the developer, who can now use prepared statements instead of calling mysql_real_escape_string.
Related
I think it is a good idea to turn off multiple statements like this to prevent this type of sql-injection.
Example of multiple statements:
$query = "UPDATE authors SET author=UPPER(author) WHERE id=1;";
$query .= "UPDATE authors SET author=LOWER(author) WHERE id=2;";
$query .= "UPDATE authors SET author=NULL WHERE id=3;";
pg_query($conn, $query);
Is it possible to prevent multiple statements in posgresql settings or for example using posgre's related PHP code?
Or maybe there is any way of parsing SQL queries before passing them to pg_query in order to detect queries which consists of more than one statement?
No, there is no way to disable multi-statements in PostgreSQL. Nor, as far as I know, is there any way to do so in the PHP Pg or PDO PostgreSQL drivers.
They aren't your problem anyway. Disabling multi-statements might be a (slight) SQL injection harm mitigation, but it wouldn't be any real protection. Consider writeable CTEs, for example, or qualifier removal attacks.
Instead, protect your code properly in the first place. Rigorously use parameterized statements instead of string concatenation, so there's no SQL injection opportunity in the first place. It's not hard to avoid SQL injection, you just have to be a little bit sensible with your coding practices.
Use PDO or pg_query_params for all queries, and make sure you don't concatenate text that's come from outside the immediate scope directly into SQL text, use a parameter. Even if it comes from elsewhere in the application and is considered "trusted" ... later refactoring might change that.
I think it is a good idea
It is, actually, not.
You have to prevent injections, not multiple queries.
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.
Would it be possible to prevent mysql injection using the gzcompress (and after retrieving it from the database, the gzuncompress) function? Or is there a reason why this would not work? Or is there a reason that this would not be a good idea at all?
This is a bad idea because
Theoretically, there might be a sequence of data that, when compressed, leads to a SQL injection or simply breaks the query
gzcompressed data can't be properly indexed and searched - you'll have a database full of garbled characters
gzcompression is computationally expensive
simply always sanitize your data before entering it into a database, using the string escaping method of your library (like mysql(i)_real_escape_string()) or parametrized queries.
If you do that reliably, no further protection is necessary.
to protect against SQL Injection attacks, use PDO's parameterized queries.
SQL injection can be prevented 1 of 2 ways. You can use parameterized queries or you can properly sanitize values when building your SQL statements.
Now, what you are suggesting will probably prevent malicious injections into the database, but that does not eliminate the possibility that will introduce SQL syntax errors (effectively SQL injection) into your SQL statements.
Also, by using compression functions, it will eliminate the possibility of viewing or searching the contents of the database without going through decompression.
This is a novel approach to avoiding SQL injection, but will cause you more problems than it actually solves. You really need to stick with the tried and true solutions.
OWASP - SQL Injection
Steve Friedl's Unixwiz.net Tech Tips - SQL Injection Attacks by Example
MSDN - SQL Injection
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.