69

In both queries 1 and 2, the text from the textbox is inserted into the database. What's the significance of the parameterized query here?

  1. Passing txtTagNumber as a query parameter

    SqlCommand cmd = new SqlCommand("INSERT INTO dbo.Cars " +"VALUES(@TagNbr);" , conn);
    cmd.Parameters.Add("@TagNbr", SqlDbType.Int);
    cmd.Parameters["@TagNbr"].Value = txtTagNumber.Text;
    
  2. Converting txtTagNumber to an integer before constructing the query

    int tagnumber = txtTagNumber.Text.ToInt16(); /* EDITED */
    INSERT into Cars values(tagnumber.Text); /* then is it the same? */
    

Also, here I would use Regular Expression validation to stop insertion of illegal characters.

jpaugh
  • 6,634
  • 4
  • 38
  • 90
sqlchild
  • 8,754
  • 28
  • 105
  • 167
  • 8
    Why write your own validation when parameterized queries already solve the problem? – OJ. Mar 29 '11 at 05:55
  • Plus validation is hard on free from text input, and Parameterized queries do proper "escaping" ( the client actually pass the data directly to the server ). – dvhh Mar 29 '11 at 06:05
  • @dvhh: can you please give an example of ESCAPING? – sqlchild Mar 29 '11 at 06:10
  • an !invalid! escaping would be for example String.replace("'","''"). Parameterized execution command use another form of encoding that there is little need for you to know – dvhh Mar 29 '11 at 06:16
  • Possible duplicate of [Why do we always prefer using parameters in SQL statements?](http://stackoverflow.com/questions/7505808/why-do-we-always-prefer-using-parameters-in-sql-statements) – jmoreno Feb 28 '17 at 20:49

6 Answers6

60

Parameterized queries do proper substitution of arguments prior to running the SQL query. It completely removes the possibility of "dirty" input changing the meaning of your query. That is, if the input contains SQL, it can't become part of what is executed because the SQL is never injected into the resulting statement.

max23_
  • 6,531
  • 4
  • 22
  • 36
OJ.
  • 28,944
  • 5
  • 56
  • 71
  • @OJ : can you give an example please? like if i give DROP table cars , then what would the parameterized query do? – sqlchild Mar 29 '11 at 06:06
  • 1
    @sqlchild: table, column or procedure names (well identifiers in general) cannot be parameterized, only "values" or "arguments" (as OJ said). Like used in WHERE or JOIN/IN clauses, parameters to functions or procedures, etc. Hence the name "parameterized" queries. – Christian.K Mar 29 '11 at 06:12
  • 2
    @Christian.K : sir, i meant that, if i pass DROP table Cars in the textbox , to an insert statement, insert into cars values(@carname); cmd.Parameters.Add(@carname,SQLDBTYPE varchar), then what would the parameterized query do ? – sqlchild Mar 29 '11 at 06:20
  • @OJ: also, are these two same: textbox.text.tostring() and cmd.Parameters.Add(@carname,SqlDbType varchar) ; cmdDatabase.Parameters["@carname"].Value = textBox1.Text; – sqlchild Mar 29 '11 at 06:22
  • 4
    @sqlchild: Sorry, misunderstood that. It would just insert the string "DROP table Cars" in the respective column/field. – Christian.K Mar 29 '11 at 06:23
  • @Christian.K : so is this know as escaping? – sqlchild Mar 29 '11 at 07:08
  • 2
    @sqlchild: No it is not known as escaping. It is a mechanism provided by the database to make escaping unnecessary. I think you need to read up a little more background on SQL injection (e.g. here http://en.wikipedia.org/wiki/SQL_injection) - more than fits in a comment or in a response to your original question. – Christian.K Mar 29 '11 at 07:11
  • @Christian.K : sir if i want to add multiple parameters in cmd then how to do it? will i have to write separate cmd.Parameters.ADD(@p1) ......cmd.Parameters.ADD(@p2)...? – sqlchild Mar 29 '11 at 07:26
  • 3
    @sqlchild: Your starting to change the topic and have already accepted the answer to your original question anyway. Please consider posting another/new question about other things you need to know. This is how SO is supposed to work and allows for better discoverabilty and benefits everyone. – Christian.K Mar 29 '11 at 07:34
  • 1
    Christian: Thanks for following up with the answers mate. I was away from my machine for the last few hours and you've saved me from having to clarify. +10 mate :) – OJ. Mar 29 '11 at 09:42
  • "parameterized queries" do no help if there is dynamic sql being created in sql (such as might happen in a stored procedure), and then being executed as exec query or exec sp_executeSQL query – jmoreno Feb 28 '17 at 20:52
40

Imagine a dynamic SQL query

sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND
Pass=' + password

so a simple sql injection would be just to put the Username in as ' OR 1=1-- This would effectively make the sql query:

sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS='
+ password

This says select all customers where they're username is blank ('') or 1=1, which is a boolean, equating to true. Then it uses -- to comment out the rest of the query. So this will just print out all the customer table, or do whatever you want with it, if logging in, it will log in with the first user's privileges, which can often be the administrator.

Now parameterized queries do it differently, with code like:

sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'

parameters.add("User", username) parameters.add("Pass", password)

where username and password are variables pointing to the associated inputted username and password

Now at this point, you may be thinking, this doesn't change anything at all. Surely you could still just put into the username field something like Nobody OR 1=1'--, effectively making the query:

sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND
Pass=?'

And this would seem like a valid argument. But, you would be wrong.

The way parameterized queries work, is that the sqlQuery is sent as a query, and the database knows exactly what this query will do, and only then will it insert the username and passwords merely as values. This means they cannot effect the query, because the database already knows what the query will do. So in this case it would look for a username of "Nobody OR 1=1'--" and a blank password, which should come up false.

Source: lavamunky.com; Nov 2011

TylerH
  • 20,799
  • 66
  • 75
  • 101
23

SQL injection happens when a possible parameter has SQL within it and the strings are not handled as it should be

eg:

var sqlquerywithoutcommand = "select * from mytable where rowname =  '" + condition+''";

and the condition is a string coming from the user in the request. If condition is malicious say eg:

var sqlquerywithoutcommand = "select * from mytable where rowname =  '" + "a' ;drop table  mytable where '1=1"+"'";

you could end up running malicious scripts.

However, using parameters the input will be cleaned of any characters which might escape string characters, which means you can be ensured no matter what comes in it will not be able to run inject scripts.

Using the command object with parameters the SQL actually executed would look like this:

select * from mytable where rowname = 'a'';drop table mytable where 1=1'''

in essence it will be looking for a row with rowname = a';drop table mytable where 1=1' and not running the remaining script.

TarHalda
  • 1,050
  • 1
  • 9
  • 27
Whimsical
  • 5,985
  • 1
  • 31
  • 39
  • 2
    but when sql takes the value from the parameter, then how does it reads it, i mean it would take it in the same way as directly from the string , i.e. it would read it as drop table mytable , or am i wrong? – sqlchild Mar 29 '11 at 06:13
  • @ sqlchild :nope...it escapes all the ' with '' so that the entire string becomes the parameter...let me add this to the answer – Whimsical Mar 29 '11 at 06:16
5

Parameterized queries handles everything - why go to the trouble?

With parametrized queries, in addition to general injection, you get all the data types handled, numbers (int and float), strings (with embedded quotes), dates and times (no formatting problems or localization issues when .ToString() is not called with the invariant culture and your client moves to a machine with and unexpected date format).

Cade Roux
  • 88,164
  • 40
  • 182
  • 265
  • They surely handle SQL injection but not other kind of injections (mostly web side injection like javascript). – dvhh Mar 29 '11 at 06:12
2

It is quite understandable why one would feel so.

sqlQuery = "select * from users where username='+username+';"

vs

sqlQuery = "select * from users where username=@username;"

Both the above queries seem to do the same thing.But they actually don't.

The former uses input to for a query, the latter decides on the query but only substitutes the inputs as it is during the execution of the query.

To be more clear, the parameters' values are located some where on the stack where the variables' memory is stored and is used for search when needed.

So if we were to give ' OR '1'='1 as the input in username, the former would dynamically construct a new queries or queries as part of the sql query string sqlQuery which is then executed.

While on the same input, latter would search for ' OR '1'=' in the username field of the users table with the statically specified query in the query string sqlQuery

Just to consolidate it, this is how you use parameters to make query:

SqlCommand command = new SqlCommand(sqlQuery,yourSqlConnection);

SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@username";
parameter.Value = "xyz";

command.Parameters.Add(parameter);
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ant_1618
  • 1,861
  • 4
  • 17
  • 26
2

Parameterized queries allow the client to pass the data separately form the query text. Where on most free from text you would do validation + escaping. Of course Parameterization don't help against other kind of injection, but as the parameter are passed separately, they are not use as execution text query.

A good analogy would be the "recent" execution bit used with most of the modern processor and Operating system to protect from buffer overflow. It still allows the buffer overflow but prevent the execution of the injected data.

dvhh
  • 4,724
  • 27
  • 33