views:

4086

answers:

7

I have created a small survey web page on our company Intranet. This web page is not accessible from the outside.

The form is simply a couple of radio buttons and a comments box.

I would like to maintain good coding practices and would like to guard against SQL Injections.

Can SQL injections happen on a insert statement with comments from the textbox? If so, how can I guard against it using .NET 2.0?

+19  A: 

Use parameterized queries so that the text is automatically quoted for you.

SqlCommand command = connection.CreateCommand();
command.CommandText = "insert into dbo.Table (val1,val2,txt) values (@val1,@val2,@txt)";
command.AddParameterWithValue( "val1", value1 );
command.AddParameterWithValue( "val2", value2 );
command.AddParameterWithValue( "txt", text );

...
tvanfosson
+24  A: 

Injection can happen on any SQL statement not run properly.

For example, let's pretend your comment table has two fields, an integer ID and the comment string. So you'd INSERT as follows:

 INSERT INTO COMMENTS VALUES(122,'I like this website');

Consider someone entering the following comment:

'); DELETE FROM users; --

If you just put the comment string into the SQL without any processesing this could turn your single INSERT in to the following two statements followed by a comment:

INSERT INTO COMMENTS VALUES(123,''); DELETE FROM users; -- ');

This would delete everything from your users table. And there are people willing to spend all day finding the right tablename to empty using trial and error and various tricks. Here's a description of how you could perform an SQL Injection attack.

You need to use parameterized SQL statements to prevent this.

And this isn't just for security reasons. For example, if you're creating your SQL statements naively the following comment:

I'm just loving this website

would cause an SQL syntax error because of the apostrophe being interpreted by SQL as a closing quote.

Dave Webb
nice point on the apostrophe - I have been using the string.replace method - but I can see this is much easier.
Brad
Very well explained. Nicely done.
Jeremiah Peschka
Even a name would cause a problem if not done as a parameter, eg O'Tool, O'Rourke.
Martin
We had a girl named Ja'Net come work for my company. That really screwed some stuff up. Most of that code was written before I got here though.
Aaron Smith
A: 

The easiest way to guard against that form of SQL injection, is to use parameters and stored procedures rather then building sql statements to run. (In C# or internally to SQL Server).

However I'm not entirely sure you should be spending time on this, unless of course it's your corporate policy, as the chances of it ever occuring internally are minimal at best, and if it did occur, I would hope you would know immediately who it is.

Bravax
Of course, a disgruntled employee would never try to hose your company database. You ALWAYS need to worry about security and follow best practices.
tvanfosson
I disagree. This is an internal web page, which any ex-employee should not be able to access. Also I would guess (or certainly hope), that all internal traffic is logged.Security needs, must be evaluated along with other critiera, and may not be justified in a number of situations.
Bravax
Who says you have to be an ex-employee to be disgruntled? Good security is preventing damage, not assigning blame afterwards. In this case the cost of using parameterized queries is not even very high. It should be the norm when constructing queries by hand.
tvanfosson
I think not allowing a user to (un)intentionally delete your data is always a security need. Why would one not sanitize the inputs? What gains could one possibly get by avoiding it? It's not that we are having to double the efforts to get it done right. I'm not downvoting you but I disagree.
Learning
I agree if this was coded like that from the start, however going back and changing it is possibly a waste of time. I did say possibly remember. It just needs to be weighed up against other work requirements and corporate policy.
Bravax
@TVanfosson, Certainly internal employee's can be disgruntled, but this is an internal survey. Is it worth it ensuring a disgruntled employee can't go out of his way and break it? I agree it should be the norm, but security like this can't be forced on people. It must be weighed againstother costs
Bravax
If you're creating your SQL statements using String concatenation instead of a parameterised and there's an apostrophe or quote in the String the statement will fail. It won't be an injection attack but the user will get a 500 error and their post won't be saved.
Dave Webb
Internal empployees are often a greater threat than external. Plus, it is better to learn good practices as you go. Once you know how to do it correctly, it isn't that much more timeconsuming (if at all) to do it for everything.
HLGEM
@Dave and HLGEM I agree with you both, but this is for existing code, thus the time and cost to refactor it must be weighed up against the maintenance/security benefits.
Bravax
A: 

Yes, it can. Let's say the client sends this:

OR 1 = 1

That can be very painfull for your

  SELECT * FROM admin WHERE name = @name AND password = @password

You can prevent this with

boj
The question was explicitly about INSERT statements.
Dave Webb
true. but maybe the list helps
boj
A: 

Yes, they can happen. The easiest way to guard against this is to use prepared statements rather than building the SQL manually.

So, rather than this:

String sql = 
 String.Format("INSERT INTO mytable (text_column) VALUES ( '{0}' )",
   myTextBox.Text); // Unsafe!

You would do something like this:

String sql = "INSERT INTO mytable (text_column) VALUES ( ? )"; // Much safer

Then add the text of the text box as a parameter to your DbCommand which will cause it to be automatically escaped and replace the "?" in the SQL.

Eric Petroelje
A: 

In addition to using prepared statements and parameters rather than concatenating strings into your SQL you should also do the following:

  1. Validate and format user input on the server side. Client side validation and limits can easily be bypasses with tools like WebScarab, or by spoofing your form.

  2. Configure appropriate permissions for the database user account. Web application should use a separate account or role in your database with permissions restricted to only the tables, views and procedures required to run your application. Make sure that user does not have select rights on the system tables

  3. Hide detailed error messages from users, and use less common names for your objects. It amazes me how often you can determine the server type (oracle, mysql, sqlserver) and find basic schema information in an error message and then get information from tables called 'user(s)', 'employee(s)'. If you haven't set your permissions as in (2) and I can determine your server type you are open to statements like this for SQL Server

    SELECT table_name FROM information_schema.table

    EXECUTE sp_help foundTableName

Gary.Ray
+1  A: 

SQL injection can happen any time you pass a query back to the database. Here's a simple demonstration:

SQL Injection Explained

The key, within .NET, is to do as Dave Webb has given. It will prevent the injection attempt by encompassing the entire string as one parameter to be submitted, handling all characters that might be interpreted by SQL Server to change the query or append additional commands.

And it should be pointed out that SQL injection can occur on any application, not just web applications. And that an internal attack is usually the most costly to an organization. One cannot safely assume that an attack won't originate from within.

K. Brian Kelley