views:

319

answers:

13

I know it's a simple question, but in everything I've read, I've never seen this spelled out specifically.

If you do a query on a page, do you need to worry about SQL injection attacks? Or is it only a problem when you ask the user for input?

Thanks!

+3  A: 

SQL Injection snippets can also come in from the QueryString (aka "URL arguments") passed in with the GET method instead.

As hinted by Billy O'Neal [single quote intended ;-) ], any piece of data that is not intrinsic to the program (or to its very trusted back-end), should be "sanitized". The Sanitizing term seems to imply to be a sophisticated process, but in effect it typically means little more than:
[may vary with your specific SQL server make]

  • remove (or escape) single quotes characters embedded within a string
  • watch from strings exceeded the length of the underlying SQL column (in particular if such length is readily long)

A possible reason for the idea that HTTP Forms would be the only source of SQL injection snippets is that a -valid- recommendation is to ensure that one gets the user-supplied submitted text from the Request's form exclusively. Several Web Application frameworks expose the HTTP request as an object which exposes, by default, all key-values pairs from either the QueryString, from a Form, or even from cookies, accessible as from a single hash. While this can be practical for applications that sometimes get the info from a form an sometimes from the querystring, this can facilitate the work of would-be-injectors, because it is easier to craft a URL than a Form. (But with the proper tool, one can also fake a POST request as well...)

mjv
A: 

When the user can modify the values of the parameters of a query, then it can become a threat.

despart
+2  A: 

No, there are several other cases. For example, you may have some of the variables as a querystring passed into a php page. The 'user' could modify that string to include some dodgy scripting.

http://en.wikipedia.org/wiki/SQL_injection includes a large section on the types of vulnerabilities and how to combat them effectively.

Mark Mayo
+2  A: 

To summarize - any type of input from the user that is used in SQL queries is a potential target of sql injection

Bozho
+4  A: 

SQL injection is caused by unsanitized data. You should always always always sanitize data going into a database. Not just for SQL injection, but also for making your app just work.

For example, some systems won't use my name because it has a ' character in it, and their database is not sanitized. I did not enter my name, my name was taken from another database. Doesn't matter -- the data should be sanitized.

Billy ONeal
A: 

You need to worry about cross site scripting (XSS) attacks in this case if the data you are displaying on the page came from user submitted data.

ESCAPE INPUT, FILTER OUTPUT

cballou
+1  A: 

Also consider preventing against cross-site-scripting ("XSS").

a paid nerd
+1  A: 

SQL Injections is possible if you use any kind of data that comes from the browser. It could be form data, querystring data, cookie values, or even data from the request header.

The obvious and easy ways in is the form data and querystring data, but anything that comes from the browser could be spoofed.

Guffa
+1  A: 

Anything that the code takes as input from the HTTP request can be a SQL injection vector:

  • POST/PUT content
  • GET URL parameters
  • Cookies

At a higher level these show up as $_REQUEST or Page.Request values, session variable, it all depends on a miriad of factors. but ultimately, is not just POST forms. Although probably the most prvalent vector is form POST content and GET URL variables.

Remus Rusanu
A: 

As I concern you should never trust this variables: $_POST, $_GET, $_REQUEST, $_COOKIE even $_SERVER can contain malicious code. So ALWAYS make sure that inserted data match your expectation. For example as an extra paranoid measure on validation email address you can encrypt email address with md5 like this:

"SELECT username FROM users WHERE MD5(email)='" . md5($_POST['email']) . "' AND active=1"
Nazariy
A: 

As a general rule parameterized queries should always be used.

  1. It prevents malicious user input from being executed against your database (SQL injection attacks). [You should do user input validation as well to ensure that malicious code isn't rendered on the page and that JavaScript can be run against your server.]
  2. It enables you to re-use your queries.
  3. You can precompile your queries.
  4. It organizes your input and makes it more readable. You might want to use the same parameter in more than one location.
  5. It has better support for different data type such as dates, strings and the like. You won't run into problems with weird characters when you use parameterized queries.

In my use case I always generate parameter based queries. I have a wrapper that will always compile them so that if a second query gets executed in the same request path, it will run that much faster on the same connection. This takes a fair bit of work to setup, but is worth the performance gain in any medium to enterprise level system.

Middletone
+15  A: 

You don't have to have user input to suffer a SQL injection attack.

Let's say you have a product page that is called using a URL such as this:

product.aspx?ID=123

And in your code you have a query constructed such as this:

sql = "Select * From Products Where ID = " + Request.Querystring["ID"];

Someone could call your page with this:

product.aspx?ID=123;DROP Table Students;

And bam, you've just been had.

In addition to ANYTHING that can be passed in via a user, querystring, post, cookie, browser variable, etc. I think it is just good practice to always use parameters, even if you have the literals in your code. For example:

if(SomeCondition)
{
    sql = "Select * from myTable where someCol = 'foo'";
}
else
{
    sql = "Select * from myTable where someCol = 'bar'";
}

this may be injection safe, but your RDBMS will cache them as two different queries. if you modiy it to this:

sql = "Select * from myTable where someCol = @myParam";
if(SomeCondition)
{
   myCommand.Parameters.Add("@myParam").value = "foo";
}
else
{
   myCommand.Parameters.Add("@myParam").value = "bar";
}

You achieve the same result but the RDBMS will only cache it as one query, substituting the parameter at runtime. I use it as a rule of thumb to ALWAYS use parameterized queries, just to keep things consistent, not to mention a slight cache improvement.

Neil N
You have to remember to pre-compile the query before sending it to the DB and it must be on the same opened connection.
Middletone
Good answer. @Middletone: for SQL Server, no such thing as precompile for and plans are independant of connections.
gbn
My expereince is that unless you precompile a statement it won't be saved in memory unless it's a part of a stored procedure. I've worked a lot with queries and this is a consistent pattern. In asp.net code precompiling the statement makes a profound difference in the query execution time.
Middletone
Middletone, what DB server are you talking about?
Neil N
SQL Server specifically.
Middletone
@Middletone: if you're so convinced, demonstrate to me how you'd precompile SQL Server statements.
gbn
I think Middletone is thinking of a different DB
Neil N
A: 

I agree that parameterisation is the best approach.

As an alternative (which might be easier to retro fit into your code, at least initially) doubling the single quotes in a string will prevent SQL Injection.

To take Neil N's example:

sql = "Select * From Products Where ID = " + Request.Querystring["ID"];

wrap the variable in a function that doubles the quotes, and wrap the varible with single quotes too.

sql = "Select * From Products Where ID = " 
    + fnSQLSafeParam(Request.Querystring["ID"]);

The function would be something like (VBscript example):

Function fnSQLSafeParam(ByVal strStr)
  If IsNull(strStr) or IsEmpty(strStr) then strStr = ""
  fnSQLSafeParam = "'" & replace(Trim(CStr(strStr)), "'", "''") & "'"
End Function
Kristen