tags:

views:

294

answers:

3

I use an API that expects a SQL string. I take a user input, escape it and pass it along to the API. The user input is quiet simple. It asks for column values. Like so:

string name = userInput.Value;

Then I construct a SQL query:

string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'",
                           name.replace("'", "''"));

Is this safe enough? If it isn't, is there a simple library function that make column values safe:

string sql = string.Format("SELECT * FROM SOME_TABLE WHERE Name = '{0}'",
                           SqlSafeColumnValue(name));

The API uses SQLServer as the database.

Thanks.

Seva Alekseyev thank you so, so, so much for reading my question and trying to answer it. Thank you for not preaching to me about "best practices". And thank you for not trying to "educate me" Really, thank you!

+5  A: 

Parameterise it!

A Google search of SO for "SQL injection"

Edit:

In response to Seva Alekseyev, SO answer with character 8 injection

gbn
Given that his question starts with "I use an API that expects a SQL string" that may not be an option.
Jacob G
@Jacob G: surely we should try to educate...
gbn
If you have access to the code of the api, check to make sure that it uses argument parametrization. What do you actually pass to the api? That should help in derermining what is used to pass the argument.
Joe Pitz
@gbn: It seems that the poster knows that the input needs to be sanitized, else they wouldn't be asking the question.
Jacob G
@Jacob G: true, but why reinvent the wheel if you don't have to? I'd be questioning why I have to use an API like this too.
gbn
@gbn: lotsa reasons. Legacy code, I would presume. Anyway, just answer the question, instead of promoting a best practice. This particular best practice does not need any more promotion.
Seva Alekseyev
@Seva Alekseyev: yes it does require more promotion to prevent questions like this...
gbn
@gbn: chr(8) injection only works if the SQL string is passed through a console on its way to the database. Read the comments on that answer.
Seva Alekseyev
+5  A: 

Simple:

const string sql = "SELECT * FROM SOME_TABLE WHERE Name = @name";

and add the @name parameter with value:

cmd.CommandText = sql;
cmd.Parameters.AddWithValue("@name", name);
Marc Gravell
He still needs to get the actual SQL statement out of the command object to pass to the API.
manu08
A: 

Since using SqlParameter is not an option, just replace ' with '' (that's two single quotes, not one double quote) in the string literals. That's it.

To would-be downvoters: re-read the first line of the question. "Use parameters" was my gut reaction also.

EDIT: yes, I know about SQL injection attacks. If you think this quoting is vulnerable to those, please provide a working counterexample. I think it's not.

Seva Alekseyev
-1: And how does that protect against things like Little Bobby? (http://xkcd.com/327/ if you don't know what that means). While parameters may not be an option, the solution of replacing single with double quotes is certainly not 'it' as your answer states.
Greg Beech
There's a little ' after Robert. That's how. When properly quoted, Bobby's unorthodox name would stored in the database in its entirety.
Seva Alekseyev
I was speaking figuratively. You wouldn't have quotes with, for example, numeric arguments. It's this *kind* of thing that is the problem, not that exact example. (For example, that exact syntax wouldn't work with SQL Server, but the problem still applies.)
Greg Beech
you can invalidate this replace by using character 8, backspace. Or "high" unicode characters matching '
gbn
@Greg: I'm with you. This method is a nonstarter and should not be encouraged.
Steven Sudit
Not double quotes - two single quotes. That's how single quote is escaped in SQL Server. Sorry it came out that way, I've already edited. Yes, I know about SQL injection. And I said "string literals" - numeric arguments are not string literals.
Seva Alekseyev
@gbn: cite please.
Seva Alekseyev
Sure... character 8 injection: http://stackoverflow.com/questions/1800013/does-this-code-prevent-sql-injection
gbn
@gbn: If you're basing that suggestion completely on the evidence of the accepted answer in that post, I suggest reading the comment I added and trying it for yourself.
Jon Seigel
@gbn: debunked... Keep trying :) String quoting is like pointer arithmetic in C or dancing on a minefield: inherently dangerous, but works if done right.
Seva Alekseyev
Seva Alekseyev thank you so, so, so much for reading my question and trying to answer it. Thank you for not preaching to me about "best practices". And thank you for not trying to "educate me" Really, thank you!
sri
Um, for the record, I still think that parameters are the way to go :) However, I've been in this business long enough to understand the existence of constraints on your designs. Been there, done that.
Seva Alekseyev
@Seva While everyone knows the code above is subject to injections, sometimes you are tied to an API that just doesn't allow you to follow best practices. Too often programmers worry about stuff that isn't within the circle of concern of a particular task. Good answer to the specific question.
Nissan Fan
@Seva I would do the same thing, but in this case I can't. A couple of other times I've asked questions on SO and people want to "educate me" or question why things are setup that way, which is pretty frustrating :-)(And yes I understand about SQL injection and the other best practices...)
sri