I have a Project table with two columns - ProjectId and ProjectName - and I am writing a function that creates and executes SqlCommand to query the database for the project identifiers with the given name. This command works, but is vulnerable to SQL Injection :
string sqlCommand = String.Format("SELECT {0} FROM {1} WHERE {2} = {3}", attributeParam, tableParam, idParam, surroundWithSingleQuotes(idValue)); SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection); using (SqlDataAdapter adapter = new SqlDataAdapter(command)) { DataTable attributes = new DataTable(); adapter.Fill(attributes); ... }
attributeParam , tableParam , idParam and idValue are all rows. For example, they can be "ProjectId" , "Project" , "ProjectName" and "MyFirstProject" respectively. surroundWithSingleQuotes surrounds the string with '' , so surroundWithSingleQuotes(idValue) == "'MyFirstProject'" . I am trying to write this function as general as possible, since I might want to get the whole given attribute from the table in the future.
Although the above String.Format works, it is not:
string sqlCommand = String.Format("SELECT @attributeparam FROM {0} WHERE " + "@idparam = @idvalue", tableParam); command.Parameters.Add(new SqlParameter("@attributeparam", attributeParam)); command.Parameters.Add(new SqlParameter("@idparam", idParam)); command.Parameters.Add(new SqlParameter("@idvalue", surroundWithSingleQuotes(idValue))); SqlCommand command = new SqlCommand(sqlCommand, sqlDbConnection); using (SqlDataAdapter adapter = new SqlDataAdapter(command)) { DataTable attributes = new DataTable(); adapter.Fill(attributes); ... }
I'm not sure why. I am not getting an error, but when I populate my DataTable with the SqlDataAdapter , the DataTable does not contain anything. Here are a few approaches that I have taken, to no avail:
- After this answer and the Microsoft documentation , using
AddWithValue or using Parameters.Add and SqlParameter.Value . - selectively replacing
{0} , {1} , {2} and {3} in String.Format either the actual value or the parameter string.
Elsewhere in my code, I used parameterized queries (albeit with one parameter) without problems.