What are ALL THE MySQL commands that can be used to do an injection in a code?
I have disabled UNION and CONCAT.
I have a very basic application so no need for any complex queries so what else can I disable to make sure injections are a non issue?
Yes I have sanitized all variables as far as I know. The issues is it is a project with multiple parties and I have noticed some sloppy work in some libraries I have been handed to work with.
I was thinking on getting all the post variables sanitizing them an putting them back but that would be quite a complex task due to the complex multidimensional nature of some post variables.
Injection is possible with just about any type of SQL statement.
The only safe method of avoiding injections is to use prepared statements and bind data to query parameters.
You cannot simply disable keywords, look at this example:
SELECT id FROM user WHERE name='*' AND password = 'whatever' OR password <> ''
You need to escape the user input, before adding it to the SQL statement (e.g. mysqli_real_escape_string()). Even better would be to use prepared statements with PDO.
[…] to make sure injections are a non issue?
That cannot be done. If SQL injections are possible, then they are an issue.
Related
Is it possible to completely disable UNION SELECT queries thru a configuration option?
Besides cleaning the entry params, I would like to avoid the use of UNION since with its help it is pretty easy to implement SQL injection of the form:
SELECT * FROM users where username = '1' OR 1=1
UNION
SELECT * FROM users -- ' AND password='something'
To answer your question plainly:
No, there is no option in MySQL to selectively disable UNION.
SQL_MODE can be used to change the meaning of syntax in a couple of very specific cases, like use of double-quotes and the || operator. See https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html
But in general, you cannot disable SQL keywords or clauses, unless you whip out your code editor and modify MySQL's SQL parser code, and then build a custom instance of MySQL.
I agree with the other commenters that it isn't necessary to disable UNION if you write application code with the known practices to avoid SQL injection vulnerabilities.
Even it's easy to do SI with plain SELECT query as well and it has nothing to do with UNION at all. Moreover, as far I know, NO there is no such option to disable UNION unless you are probably taken the open source code and modified it yourself.
The best [proven] solution to avoid SQL Injection is to avoid assembling SQL statements by concatenating strings with values coming from the end user interface (or other unsafe source).
It's safer to use "Prepared Statements" and apply parameters to it, instead of concatenating those parameters.
There's still room for concatenating SQL chunks into a statements, primarily when using Dynamic SQL, but I think this is out of the scope of your question. In simple words: do not concatenate values as strings when producing a SQL statement.
According to Node.js' mysql package documentation:
In order to avoid SQL Injection attacks, you should always escape any user provided data before using it inside a SQL query. You can do so using the mysql.escape(), connection.escape() or pool.escape() methods.
I cannot find any documentation / reference to using prepared statements with mysql, except for in a reference to using '?' characters. It states the following:
Alternatively, you can use ? characters as placeholders for values you would like to have escaped...
This looks similar to prepared statements in MySQL, however it really
just uses the same connection.escape() method internally.
From my experience with talking to other developers, the general consensus in the developer community is that prepared statements are the ONLY safe way to perform mysql queries from Node.js however, as you can see with the mysql package, there is no obvious support for prepared statements. However, it is indicated that their method for avoiding SQL injection is via the usage of the escape functions.
My Question:
Are the escape functions in the mysql package sufficient enough to securely query a mysql database (without the use of prepared statements)?
Escaping is actually just as safe as using parameterized queries, if you do it consistently.
But it's recommended to use parameters because it makes your code simpler. Therefore developers are probably more likely to do it.
If the Node.js library makes it just as convenient as parameters, but implements it internally by modifying query strings, replacing the ? marks with the parameter values, then you're good.
For what it's worth, Python's MySQL driver does this too, and also PHP's PDO extension when the "emulate prepares" option is in effect. As long as those libraries are well-tested, it should be safe.
FWIW, both escaping and parameters is limited in SQL injection prevention, because in both cases, you can only protect values that you would combine with your SQL query. You cannot protect identifiers (like table names, or column names), or SQL keywords, or expressions, etc. In these cases, just be careful that you have vetted any dynamic content before combining it with your SQL query.
See also:
Preventing SQL injection in Node.js
Difference between real_escape_string and prepare()?
I need to convince someone that he needs to sanitize the user input in addition to the user of stored procedures. well I know I sound crazy but I do not feel comfortable enough with store procedures only. My first reason is that I am able to cause errors in the stored procedure but because of the fact that the application itself handles errors such that error messages are coded it is difficult for outside to understand the what there are. but I still think that this is not secure.
Does any one has a suggestion ? or am I wrong to doubt stored procedures?
No it's not safe on it's own. You can also do in a stored procedure something like this:
SET #sql = 'Select * from products where name like ''' +#spinput+''' ';
exec(#sql);
With the wrong value in #spinput you can inject code.
However you can write stored procedures that are safe against sql injection.
Even if you use proper parameters, you can still mess with the database. You could insert a script that goes in as a parameter, but when it's displayed on a web page starts doing something it shouldn't. Use parameters to ensure your database is used as intended, but also sanitize the output later - never trust user-entered data.
Using stored procedures normally protects against SQL injection, but is not the only solution to prevent SQL injections, and it doesn't protect against all forms of SQL injection.
It's not the stored procedure itself that makes the big difference, but parameterised queries, which is the most common way to call a stored procedure. By putting the values used by the query in parameters, you let the database library handle them instead of having to escape them correctly yourself.
It's possible to write code that is safe against SQL injections without using parameterised queries, but it's difficult. You have to know exactly what characters you need to escape in a string for the specific database that you are using, and if you get it wrong you are pretty much as unprotected as if you didn't know about SQL injections at all.
If you use parameterised queries, then the step of sending the values into the database is safe from SQL injection, but the query itself might not be. If the query generates and executes SQL code itself, you have the same problem with escaping strings correctly. It's however not so usual to create SQL code in the SQL code, and if you do it you are very aware of that you are doing it.
I am using mysqli prepared statements and bound variables.
Then to prevent sql injection, am I need to do anything else(eg: data type validation, filtering, sanitize, string escape etc ) with user input ?
Is there any other way of attacking MySql database other than Sql Injection ?
To prevent SQL injection you have to format your query properly.
Every literal that have to be added to the query dynamically, have to be properly formatted.
Not only data literals like strings and numbers but all of them, including operators and identifiers.
The only proper way to make values formatted is prepared statements.
For the identifiers and operators you will need also filtering, to let only allowed ones into query.
Whatever user input should not be involved at all. It's destination, not source that matters.
Is there any other way of attacking MySql database other than Sql Injection ?
sure thing. But the topic is too broad to make you secured by means of a forum post. Better hire a DBA.
I have an application which would greatly benefit by using dynamic mysql queries in combination with mysql (mysqli) real escape string. If I ran all data received from the user through mysql real escape would it be just as secure as using mysql prepared statements?
Yes, but a qualified yes.
You need to properly escape 100% of the input. And you need to properly set character sets (If you're using the C API, you need to call the mysql_set_character_set() instead of SET NAMES). If you miss one tiny thing, you're vulnerable. So it's yes, as long as you do everything right...
And that's the reason a lot of people will recommend prepared queries. Not because they are any safer. But because they are more forgiving...
Definitely NO.
While question in the title is ambiguous and can be interpreted as "Are dynamic mysql queries with every it's part properly formatted..." and thus have a positive answer, the question in the body is not:
If I ran all data received from the user through mysql real escape would it be just as secure as using mysql prepared statements?
If you look to this question closer, you will understand that this is just a magic quotes incarnation! The very purpose of this disgraced, deprecated and removed feature is exactly to "run all user input through escape".
Everyone knows nowadays that magic quotes are bad. Why positive answer then?
Okay, it seems that it needs to be explained again, why bulk escaping is bad.
The root of the problem is a quite strong delusion, shared by almost every PHP user:
Everyone have a strange belief that escaping do something on "dangerous characters" (what are they?) making them "safe" (how?). Needless to say that it's but a complete rubbish.
The truth is:
Escaping do not "sanitize" anything.
Escaping has nothing to do with injections.
Escaping has nothing to do with user input.
Escaping is merely a string formatting and nothing else.
When you need it - you need it despite of injection possibility.
When you don't need it - it won't help against injection even a little.
Speaking of difference with prepared statements, there is at least one issue (which already mentioned many times under sql-injection tag):
a code like this
$clean = mysql_real_escape_string($_POST['some_dangerous_variable']);
$query = "SELECT * FROM someTable WHERE somevalue = $clean";
will help you NOT against injection.
Beause escaping is just a string formatting facility, not injection preventer by any means.
Go figure.
However, escaping have something in common with prepared statements:
Them both doesn't guarantee you from injection if
you are using it only against notorious "user input", not as a strict rule for the building ANY query, despite of data source.
in case you need to insert not data but identifier or a keyword.
To be safe in these circumstances, see my answer explaining FULL sql injection protection how-to
Long story short: you can consider yourself safe only if you make 2 essential corrections and one addition to your initial statement:
If I ran all data received from the user through mysql real escape and always enclose it in quotes (and, as ircmaxell mentioned, mysqli_set_charset() is used to make mysqli_real_escape string() actually do it's work (in such a rare occasion of using some odd encoding like GBK)) would it be just as secure as using mysql prepared statements?
Following these rules - yes, it would be as secure as native prepared statements.
I think #ircmaxell got it right on.
As a follow-up, be on the lookout for this kind of thing.
I used to do it all the time:
<?php
//sanitize the dangerous posted variable...
$clean = mysql_real_escape_string($_POST['some_dangerous_variable']);
//...and then forget to use it!
$query = "SELECT * FROM someTable WHERE somevalue = '{$_POST['some_dangerous_variable']}'";
?>
And when I say "used to do it", what I mean is that I eventually gave up and just started using prepared statements!