Does Using Parameterized SQLcommand Make My Program Immune to SQL Injection

Does using parameterized SqlCommand make my program immune to SQL injection?

I'd say for your particular, and probably canonical, example for parametrized queries, yes it is sufficient.

However, people sometimes write code like this

cmd.CommandText = string.Format("SELECT * FROM {0} WHERE col = @col;", tableName);
cmd.Parameters.Add("@col", ...);

because there is simply no way to pass the tablename itself as a parameter and the desire to do exists sometimes - misguided or not. It seems it is then often overlooked, that tableName (unless maybe only read from a set of static/constant values that do not derive from any input) indeed allows for SQL injection.

Are Parameters really enough to prevent Sql injections?

Placeholders are enough to prevent injections. You might still be open to buffer overflows, but that is a completely different flavor of attack from an SQL injection (the attack vector would not be SQL syntax but binary). Since the parameters passed will all be escaped properly, there isn't any way for an attacker to pass data that will be treated like "live" SQL.

You can't use functions inside placeholders, and you can't use placeholders as column or table names, because they are escaped and quoted as string literals.

However, if you use parameters as part of a string concatenation inside your dynamic query, you are still vulnerable to injection, because your strings will not be escaped but will be literal. Using other types for parameters (such as integer) is safe.

That said, if you're using use input to set the value of something like security_level, then someone could just make themselves administrators in your system and have a free-for-all. But that's just basic input validation, and has nothing to do with SQL injection.

Am I immune to SQL injections if I use stored procedures?

No, you will not be completely safe. As others have mentioned, parameterized queries are always the way to go -- no matter how you're accessing the database.

It's a bit of an urban legend that with procs you're safe. I think the reason people are under this delusion is because most people assume that you'll call the procs with parameterized queries from your code. But if you don't, if for example you do something like the below, you're wide open:

SqlCommand cmd = new SqlCommand("exec @myProc " + paramValue, con);
cmd.ExecuteNonQuery();

Because you're using unfiltered content from the end user. Once again, all they have to do is terminate the line (";"), add their dangerous commands, and boom -- you're hosed.

(As an aside, if you're on the web, don't take unfiltered junk from the query string of the browser -- that makes it absurdly easy to do extremely bad things to your data.)

If you parameterize the queries, you're in much better shape. However, as others here have mentioned, if your proc is still generating dynamic SQL and executing that, there may still be issues.

I should note that I'm not anti-proc. Procs can be very helpful for solving certain problems with data access. But procs are not a "silver-bullet solution to SQL injections.

Can parameterized statement stop all SQL injection?

The links that I have posted in my comments to the question explain the problem very well. I've summarised my feelings on why the problem persists, below:

  1. Those just starting out may have no awareness of SQL injection.

  2. Some are aware of SQL injection, but think that escaping is the (only?) solution. If you do a quick Google search for php mysql query, the first page that appears is the mysql_query page, on which there is an example that shows interpolating escaped user input into a query. There's no mention (at least not that I can see) of using prepared statements instead. As others have said, there are so many tutorials out there that use parameter interpolation, that it's not really surprising how often it is still used.

  3. A lack of understanding of how parameterized statements work. Some think that it is just a fancy means of escaping values.

  4. Others are aware of parameterized statements, but don't use them because they have heard that they are too slow. I suspect that many people have heard how incredibly slow paramterized statements are, but have not actually done any testing of their own. As Bill Karwin pointed out in his talk, the difference in performance should rarely be used as a factor when considering the use of prepared statements. The benefits of prepare once, execute many, often appear to be forgotten, as do the improvements in security and code maintainability.

  5. Some use parameterized statements everywhere, but with interpolation of unchecked values such as table and columns names, keywords and conditional operators. Dynamic searches, such as those that allow users to specify a number of different search fields, comparison conditions and sort order, are prime examples of this.

  6. False sense of security when using an ORM. ORMs still allow interpolation of SQL statement parts - see 5.

  7. Programming is a big and complex subject, database management is a big and complex subject, security is a big and complex subject. Developing a secure database application is not easy - even experienced developers can get caught out.

  8. Many of the answers on stackoverflow don't help. When people write questions that use dynamic SQL and parameter interpolation, there is often a lack of responses that suggest using parameterized statements instead. On a few occasions, I've had people rebut my suggestion to use prepared statements - usually because of the perceived unacceptable performance overhead. I seriously doubt that those asking most of these questions are in a position where the extra few milliseconds taken to prepare a parameterized statement will have a catastrophic effect on their application.

Does using parameterized SqlCommand make my program immune to SQL injection?

I'd say for your particular, and probably canonical, example for parametrized queries, yes it is sufficient.

However, people sometimes write code like this

cmd.CommandText = string.Format("SELECT * FROM {0} WHERE col = @col;", tableName);
cmd.Parameters.Add("@col", ...);

because there is simply no way to pass the tablename itself as a parameter and the desire to do exists sometimes - misguided or not. It seems it is then often overlooked, that tableName (unless maybe only read from a set of static/constant values that do not derive from any input) indeed allows for SQL injection.

How can prepared statements protect from SQL injection attacks?

The idea is very simple - the query and the data are sent to the database server separately.

That's all.

The root of the SQL injection problem is in the mixing of the code and the data.

In fact, our SQL query is a legitimate program.
And we are creating such a program dynamically, adding some data on the fly. Thus, the data may interfere with the program code and even alter it, as every SQL injection example shows it (all examples in PHP/Mysql):

$expected_data = 1;
$query = "SELECT * FROM users where id=$expected_data";

will produce a regular query

SELECT * FROM users where id=1

while this code

$spoiled_data = "1; DROP TABLE users;"
$query = "SELECT * FROM users where id=$spoiled_data";

will produce a malicious sequence

SELECT * FROM users where id=1; DROP TABLE users;

It works because we are adding the data directly to the program body and it becomes a part of the program, so the data may alter the program, and depending on the data passed, we will either have a regular output or a table users deleted.

While in case of prepared statements we don't alter our program, it remains intact
That's the point.

We are sending a program to the server first

$db->prepare("SELECT * FROM users where id=?");

where the data is substituted by some variable called a parameter or a placeholder.

Note that exactly the same query is sent to the server, without any data in it! And then we're sending the data with the second request, essentially separated from the query itself:

$db->execute($data);

so it can't alter our program and do any harm.

Quite simple - isn't it?

The only thing I have to add that always omitted in the every manual:

Prepared statements can protect only data literals, but cannot be used with any other query part.

So, once we have to add, say, a dynamical identifier - a field name, for example - prepared statements can't help us. I've explained the matter recently, so I won't repeat myself.

How can I avoid SQL injection attacks?

The proper way to avoid SQL Injection attacks is NOT to simply disallow certain problematic characters, but rather to use parameterized SQL. In short, parameterized SQL prevents the database from executing raw user input as part of the SQL command this prevents user input like "drop table" from being executed. Just escaping characters does not stop all forms of SQL injection attacks and excluding certain words such as "Drop" does not work in all cases; there can be certain fields where "Drop" is a perfectly valid part of the data entry.

You can find some good articles on the subject of paramaterized SQL here:

https://blog.codinghorror.com/give-me-parameterized-sql-or-give-me-death/

http://www.codeproject.com/KB/database/ParameterizingAdHocSQL.aspx

Now that you mentioned that you are working with ASP.net I can give you some links that deal specifically with SQL Injection in ASP.

https://dzone.com/articles/aspnet-preventing-sql-injectio
https://www.c-sharpcorner.com/UploadFile/75a48f/how-sql-injection-can-be-possible-in-asp-net-websites/

Here is a more general article on making your ASP more secure:
http://www.codeproject.com/KB/web-security/Securing_ASP_NET_Apps.aspx

And, of course the MSDN article on SQL injection:
http://msdn.microsoft.com/en-us/library/ms998271.aspx

Can I get SQL injection attack from SELECT statement?

To answer your questions.

A: Yes, you can get an SQL Injection attack from any query that takes parameters (even calling stored procedures if you are not using the provided methods by your platform and doing it via SQL calls).

I was asked to provide an example of how an injection can be made even by using stored procedure. I've seen applications developed that do use stored procedures, but in this way:

// C# - DON'T DO THIS!
String regionName = assignedSomewhereElse();
SQLCommand sqlCmd = DatabaseConnection.CreateCommand();
SQLCommand sqlCmd.CommandText =
String.Format("EXECUTE sp_InsertNewRegion '{0}'", regionName);

sqlCmd.ExecuteNonQuery();

Obviously, this is not the way to call a stored procedure. You should use your platform's abstractions or parametrized queries.


B: SQLDataSource is an abstraction layer for your database. It will create the SQL queries for you and automatically sanitize them in order to prevent injection.

In order to avoid injection, either:

  • Sanitize your inputs
  • Use the abstraction layer provided by your platform.
  • Use parametrized queries.

Does asp.net protect against sql injection attacks

No. As long as you're supplying the SQL, it's up to you to be smart in how you use the controls.

That usually means sanitizing input and using Parameterized Queries or Stored Procedures over dynamic SQL strings.

If the control is generating the queries for you (like the Membership Controls, etc.) then you're well protected.



Related Topics



Leave a reply



Submit