views:

569

answers:

6

I am building in C#/.NET2.0 a page that updates different columns dynamically in SQL call for example: myajaxpage.aspx?id=1111&fieldname=title

What is the correct way to build SQL query for reading column name from querystring? Is this good approach in a first place?

I tried:

cmd.CommandText = "UPDATE MyTable SET +"Request.QueryString["fieldname"]"+ = @fieldvalue WHERE id = @id";

Which works but is not secure, can you please advice how to make this query secure?

+1  A: 

not at all , you gotta have a list of possible columns , unless the users can enter whatever they want

var possibleColumns = New List<String>; // add pssobile columns here
if (possibleColumns.Contains(Request.QueryString["fieldname"])
   cmd.CommandText = "UPDATE MyTable SET +"Request.QueryString["fieldname"]"+ = @fieldvalue WHERE id = @id";
else
   Response.Write(" invalid query ");
Adinochestva
A: 

Use a SQL stored procedure instead of an ad-hoc SQL statement.

foson
+2  A: 

Definitely do not append a querystring param into the SQL like that. If you're going to do it, instead support a list of "friendly" column names in the querystring which you then map onto real field names in your table - so you're also then not exposing anything about your actual schema to the outside world.

AdaTheDev
+2  A: 

First, consider if there is another way to do this: exposing actual column names is probably a bad idea. Now a malicious user has just that much less work to do.

That said, I would consider validating your input against an expected list of values. If the value for fieldname is something you weren't expecting, you should abort before it reaches the database layer.

Finally, you should consider using square brackets to quote the field name. If a closing square bracket is found in the input, escape it by replacing it with a double closing square bracket:

[this [should]] be a valid name too]
Chris Nielsen
+2  A: 

You should abstract the field name away from the querystring altogehter. The querystring could contain some identifier that represents the field, but there is no reason to expose details of the database layout outside of the server.

Anything that comes from a browser should never be used directly in a query without verifying it. You have to verify that the field name is one of the field that you allow changing, so it's about the same amount of work to translate an independent identifier to the actual field name.

Guffa
A: 

Hi there.

Use the SqlParamterCollection.Add() method, as given in this example. You can still call the T-SQL as a text command, but you can add paramters to the SQL.

sqlCmd.CommandType = CommandType.Text;
sqlCmd.CommandText = string.Format("UPDATE MyTable SET {0} = @fieldvalue WHERE id = @id", Request.QueryString["fieldname"]);

sqlCmd.Parameters.Add("@fieldvalue", SqlDbType.VarChar).Value = "Some Value";
sqlCmd.Parameters.Add("@id", SqlDbType.Int).Value = "34";

You can also specify the size of the parameter, which is handy for string params.

sqlCmd.Parameters.Add("@fieldvalue", SqlDbType.VarChar, 10).Value = "Some Value";

So anyone trying to put a cheeky SQL statement into the @fieldValue param woudl be hindered by the max 10 chars allowed for the value. This can help limit the possibility of SQL injection attacks. Here's a good link regards SQL injection and .NET code.

In response to comment I got, you might want to verify the request querystring parameter, in case it contains potentially harmful SQL:

string fieldName = HttpUtility.UrlDecode(Request.QueryString["fieldname"]);

if (!fieldName.Contains(" "))
{
   // Do the rest of the sql code here...
}

So the idea is, if the parameter has a space, then it can't be a valid field name, so could potentially contain dangerous SQL.

Jas.

Jason Evans
Yet you inject the query string directly in there with no checking.
Colin Mackay
Yes, but I thought that next to a 'SET' command it would be difficult to inject damaging SQL e.g. "UPDATE MyTable SET SELECT * FROM tbl WHERE 1 = 1 = 'Value'" is not going to work.
Jason Evans
dangerous SQL to use as it is easily compromised. Just calling UrlDecode isn't going to protect against malicious users at all. A better solution would sanitize the string against a whitelist of allowed characters / words.
Josh E
Your edit will potentially deny perfectly valid table names (It is perfectly valid for a table name to contain a space). You should, as has been suggested by others, verify that the query string value is an actual column name (look up INFORMATION_SCHEMA.COLUMNS), or can be used to look up the actual column name (e.g. the query string isn't the column name, just a value that can be used to look up the column name)
Colin Mackay
Crap, this will teach me to leave answers when I'm tired :(
Jason Evans