if i allow users to type in a textbox and then perform a search against my db, there is the potential for sql injection. i could use regex, thats my first thought. but i had a better idea. why not see if what they typed has any SQL keywords in it. Im using an SQL Server database, in an ASP.NET program with c#, i thought microsoft would have offered an easy solution to what i am talking about. the best i can find is in this article:
Is it a programmatic way to get SQL keywords (reserved words)
which is probably what ill end up doing, but my problem is i still have to type out the entire list of keywords, there is around a hundred. sure i could be done by now instead of searching and asking this question. but isnt there an easier way? right now im going to:
1 Create a Hashset
2 add all the keywords to the hashset (cmon)
3 validate user input against the hashset
would love to see step 2 be made much easier, any other suggestions about sql injections are also appreciated
If you are passing the search text into a stored procedure and doing something like
WHERE search LIKE #inputParam
SQL will not allow injection to incur in the above fragment.
However, if you are building a string variable and then using EXEC #sql or sp_execute #SQL, you are vulnerable to SQL injection.
In my opinion, you would be better off avoiding the problem of checking for SQL keywords altogether by using parameterized SQL. Here's an example in C# (assuming you're using MS SQL Server):
using (SqlCommand sqlcmd = new SqlCommand("SELECT * FROM [MyDB].[dbo].[MyTable] WHERE [SomeColumn] = #SomeValue", sqlconnection))
{
sqlcmd.Parameters.AddWithValue("#SomeValue", strUsersSearchString);
// use sqlcmd.ExecuteReader() here
// or whatever you normally would
}
Here's another example on MSDN. This one is using parameterized SQL to call a stored procedure: http://msdn.microsoft.com/en-us/library/ff648339.aspx#paght000002_step3
Use named parameters. Dapper-dot-net makes it really easy to do this:
IEnumerable<Row> results = connection.Query<Row>("SELECT column FROM table WHERE title LIKE #query", new { query = "SEARCHTERM" });
Related
Dilemma: I have a need to build an API into another application. In this API, we must allow the developers to run SQL statements on the SQL server... Unfortunately, we are very restricted (yes, the world is upside down here) as to what we can do to minimize SQL injections... We can't create SPs on the SQL server and we can't restrict what the user can enter for his/her query either. Now while I was told that because we are building an API for "other developers", we shouldn't have to worry about SQL injection, I don't tend to agree and I'd really like to prevent that if I can...
So I was thinking that what I could do, and this is where my question comes in, is parse the query to either:
Check for SQL Injection patterns and return an error if found; or
Remove any "assignment" sections, and replace then with parameters dynamically
Are these, given my situation, the only 2 options I have? And if so, how would you implement number 2 above so that this example statement:
SELECT * FROM Table WHERE Field1='test' AND Field2=1
Becomes:
SELECT * FROM Table WHERE Field1=#Field1 AND Field2=#Field2
Where the parameters have been extracted dynamically in C#? And if so, how would I be able to extract the data type for the params? Is that possible?
You can't solve it at the application side. You can restrict as much as you can, and parse all you want, but the SQL injection attacks are contiguously evolving and new vectors are being created that will bypass your parsing.
For running ad-hoc queries I strongly recommend relying on permissions, not on SQL parsing. Users should be able to inject themselves all they want, but the permissions should prevent any damage. You won't be able to prevent (intentional or accidental) DOS from running a bad query that brings the server to its knees, but for that there is resource governance and audit.
But I can't stress this enough: you won't parse yourself out of the problem. Multi-byte character exploits are +10 years old now, and I'm pretty sure I don't know the majority of filter/parse by-pass techniques out there.
If your assignment is just writing a wrapper around a database so that other developers can send in their own SQL and get results then SQL injections are the "normal use case". There is just no way of knowing if a request is malicious or not. If you are allowed to run "good" code, you'll always be able to run "evil" code.
you can extract parameters from sql syntax
SqlConnection sqlCon = new SqlConnection("...");
String sqlScript = "Somethings ...";
Regex r = new Regex(#"(?<Parameter>#\w*)", RegexOptions.Compiled);
string[] parameters = r.Matches(sqlScript).Cast<Match>().Select<Match, string>(x => x.Value.ToLower()).Distinct<string>().ToArray<string>();
SqlCommand sqlCom = new SqlCommand(sqlScript, sqlCon);
foreach (string sqlParam in parameters)
{
sqlCom.Parameters.AddWithValue(sqlParam, "PARAMETER VALUE");
}
I have seen in my searches the use of parameterized strings in SQL queries formed as below:
SqlCommand comm = new SqlCommand();
comm.CommandText="SELECT * FROM table WHERE field LIKE '%'+#var+'%'";
comm.Parameters.AddWithValue("var","variabletext");
SqlDataReader reader = comm.ExecuteReader();
However, in this forum it was mentioned that is subject to sql injection despite it's being used in a parameterized string. I can only assume that concatenated strings bypass all parameterized security and just insert the value directly as a string. If this is the case, how does one use the wildcard operators in a parameterized query while avoiding sql code injection?
This is not vulnerable to SQL Injection.
Whoever told you that is wrong. '%'+#var+'%' is treated as data not as executable code. It is evaluated as a string then used as the pattern on the right hand side of the LIKE.
You would only have an issue if you were then to EXEC the result of such a concatenation. Simply performing a string concatenation in the query itself is not a problem.
You should use "SqlParameter" to send the values to the stored procedure does searching. The purpose of "SqlParameter" is to reject all the injection things in the values. Also if you have to execute a text containing sql code or concat the parameters, again you should set the "CommandType" property of the command to "Text" and use a "SqlParameter" to send your value to that text.
Check the Microsoft documentations about this here:
http://msdn.microsoft.com/en-us/library/ff648339.aspx
and also another question on stackoverflow here:
How does SQLParameter prevent SQL Injection?
Also take a look at here to see some specific examples:
Examples of SQL injection even when using SQLParameter in .NET?
Update:
As you have updated the question and now the way of execution is exactly specified there is no sql injection problem anymore in the code you mentioned.
Cheers
I'm working with an asp.net website that uses a lot of inline SQL queries... and I'm wondering if it is best to create the inline queries on the fly:
int i = 500;
using (SqlConnection conn = new SqlConnection(connStr))
{
SqlCommand com = new SqlCommand(conn);
...
com.CommandText = "select from table where column < #parameter";
...
}
Or to have a class to hold all queries needed for the application. Something like this:
class SqlQueries
{
private string query1 =
"select * from tblEmployees where EmployeeName = #EmployeeName";
private string query2 =
"select * from tblVacation where EmployeeName = #EmployeeName";
public string Query(string s)
{
string str = string.Empty;
switch (s)
{
case "query1":
str = query1;
break;
case "query2":
str = query2;
break;
}
return str;
}
}
Thank you!
I've used a lot of ADO.NET queries in my day and I have always used the first method. The second method is an interesting idea, but it might be cumbersome to edit those queries if you are at another place in the code that uses it. It also makes it harder to see what a query is doing at a particular place in code. Example:
string sql = "Update User set age = #age where UserId = #UserId";
tells a developer what is happening, while:
string sql = SqlQueries.Query("updateAge");
Leaves questions about what table/columns are being updated. Also, with the first one, you know exactly what params need to be added.
If you are writing this query in several places that might change things
It's not terrible to put the literal directly in the method, as long as you always call that same method every time you want to run that query. However, if you are going to copy that string literal into multiple places in your code, then a constant is definitely preferred. However, rather than taking a string as the argument for the Query method in your second example, it should take an enumeration value.
However, if you are using the second method you described, I would ask you why you don't just start using stored procedures instead?
I would recommend using stored procedures as a much better solution to your problem than hard coded in-line queries. If you have to change the query at a later date, you don't have to rebuild your application, so bugs in your query can be fixed without needing to deploy the whole application. The 2nd option you have there is a maintenance nightmare waiting to happen. It all looks so nice when you have one or two queries in it, but that begins to look a bit more ugly when you have tens or hundreds in there. Your code looks like it's c#, so I would recommend checking out the Microsoft Enterprise Library,
http://msdn.microsoft.com/en-us/library/ff632023.aspx
You might need to download a different version depending on what version of the .NET framework you are developing with.
If you absolutely have to have "inline" sql as opposed to stored procedures (and I have done this for utility type applications that merely interact with a database, rather than own it), I would suggest putting your SQL into an embedded resource file. This will make your queries easier to maintain (although you will still need to re-compile your app to make changes).
I think it's OK to have the queries "inline" as long as they aren't repeated in several places. If that starts to happen, then you might want to start creating Query classes.
In both the cases you are ultimately building/fetching String which you will pass to CommandText. So there would be no such difference. Only thing you need to consider in your case is how you would maintain the code or how will other people understand your code.
If you're going to use inline SQL at least don't put it in the web page code because it will be painful when you make database changes to know what it affects. Putting all the queries in one classes might be a bit disorganized, but if you grouped them by functional classes (like manager classes for your business objects) it might be easier to deal with.
If your queries are longer than a line or two, you should consider putting them in their own .sql file. Set the build action on the file to embedded resource, and access it with a call to GetManifestResourceStream(). That way, you're elevating your sql to the status of a proper language, with syntax highlighting, validation and intellisense (when you connect VS to your DB). Needless to say, this hugely facilitates maintenance.
If all this seems like a hassle, grab my VS extension, QueryFirst. Create your .sql files with the provided template and they will automatically be wired up for compilation. But you won't care because you'll just access the queries via the generated classes.
Sql is the only computer language I can think of that we accept to see chopped up in string literals. It ought to be a scandal.
I want to use ODP.NET to run various queries on an oracle database and I'd like to use parameters in the query. Here's a trivial example snippet (omitting all the obvious setup bits of the OracleConnection):
string query = "SELECT FIRSTNAME FROM EMPLOYEES WHERE LASTNAME=:pNAME";
OracleCommand command = new OracleCommand(query);
command.Parameters.Add(":pNAME", OracleDBType.Varchar2).Value = "O'Brien";
My question is, is there anyway to see the query that gets generated from this? I know this is a simple example and the output is probably very obvious, but I'm trying to see how it actually handles things like escaping characters such as the ' in O'Brien. And of course in the future if my queries get more complicated and I'm getting sql errors, I thought I might be able to use the generated query to debug.
Any help or pointers is greatly appreciated!
SQL parameters are passed as parameters directly to SQL server, so there is no way to see it from your application. You can try checking it from Oracle side.
Why table params aren't allowed in SQL Server? Is there any solution to this?
Example:
using (SqlCommand myCommand = new SqlCommand("SELECT * FROM #table WHERE USERNAME=#username AND PASSWORD=HASHBYTES('SHA1',
#password)", myConnection))
{
myCommand.Parameters.AddWithValue("#table", table);
myCommand.Parameters.AddWithValue("#username", user);
myCommand.Parameters.AddWithValue("#password", pass);
myConnection.Open();
SqlDataReader myReader = myCommand.ExecuteReader())
...................
}
Thanks.
You can't paramaterise that part of the SQL. The server needs to know the name of the table to be able to 'prepare' the query, which is done before the parameters are processed.
You might dynamically generate the query, but that may open you up to SQL injection attacks and run-time SQL syntax errors. Also, there is a saving to be had if an SQL statement can be cached by the server - you'll loose that if every query is dynamically generated.
Why? Because the benefit of flexibility is minor compared to the nightmare it would create in query optimization and validation.
As a sidenote, even if it was recognised you'd be getting a quoted string in the SQL, not just the table name. Dynamic SQL with heavy validation is the only real way of doing this.
If you have to pass a table of values...
XML parameter
CSV (String) parameter
Parse in SQL. See "Arrays and Lists in SQL Server 2005"
Otherwise, what are you trying to do?
Edit: I've got it now. As others mentioned, SQL does not work like that.
No, you cannot pass the table name as a param.
The best way would be to try using String.Format for the table name.
I would try to ilustrate my point of view about this with an example:
If you go to buy a car, you can "parametrize" some thinks: You can change the colour, may be some variations of the engine, you can put an MP3 or not, ... but you cant change the car model. If you change the car model, this is not a parameter, this is another car.
It is the same with sql query, the table is not a parameter is part of the sentence itself, same way that the command is (select, update) .. so you can't do #command from #table. If you change the table, this is another sentence, like the car.
(this is not a technical "because" answer for you question, but a conceptual point of view for better understanding of the techical part that others are posting)
My two cents.