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
Related
I am struggling with proper parameter passing to a MySQL query. In MySQL workbench, my query works fine, but not in the C# code. I assume it is due to wrong parameter passing.
That's why I'd like to see what precisely do I pass to the cmd.ExecuteScalar() method. But I can't figure out how to determine the cmd string.
In debugger I only get query with formal parameters, not passed ones. And even by using cmd.ToString() I get this nonsense:
MySql.Data.MySqlClient.MySqlCommand.
Here is my code:
string timeStampStr = timeStamp.ToString("yyyy-MM-dd hh:mm:ss");
...
MySqlCommand cmd = new MySqlCommand("SELECT COUNT(*) FROM plc WHERE plc.last_communication < #timeThreshold AND plc.id = #plcId", _conn);
cmd.Parameters.AddWithValue("#timeThreshold", timeStampStr); // Is this correct ? timeStampStr is a string
cmd.Parameters.AddWithValue("#plcId", plcId);
object result = cmd.ExecuteScalar();
Thank you !
Your best bet is probably to enable the query log on MySQL and use that to profile what was sent to the database engine.
This is because the application code doesn't actually replace the placeholders with the parameter values, the database engine does. The application code invokes the parameterized query and supplies the parameters simultaneously. (As a bit of a side-effect, this allows database engines to cache execution plans for parameterized queries much more effectively, since the query itself doesn't change. This provides a slight performance improvement when using parameterized queries over concatenated values.)
And even by using cmd.ToString() I get this nonsence: MySql.Data.MySqlClient.MySqlCommand.
That's not nonsense, that's the name of the class on which you're calling .ToString(). The default behavior of .ToString() for reference types is to return the name of the type, unless you override it.
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");
}
This question already has answers here:
How does SQLParameter prevent SQL Injection?
(4 answers)
Closed 8 years ago.
I hope this is the right place to ask, how does parameters.addwithvalue work? I am thinking in a way to protect against SQL injection? I have been looking quite a lot on Stackoverflow, and a lot of people say "//Against sql injection". I have been using it blindly, but now that I have to hand in a paper about my assignment I need to explain why it is protection. I have been trying to find something on MSDN, found this one:
SQL injection But it uses the parameters.add. I then read that they replace .Add with .AddWithValue, is that true? Any official on this then?
So basically, anyone better in searching for some official paperwork that it protect against SQL injection? Or can tell me how it works?
I am not trying to make you do my work, I just can't find it my self.
I am using it like this:
using (SqlConnection conn = new SqlConnection(connectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
String queryString = "DELETE FROM dbo.SecurityAccess WHERE Username = ' #Username ";
cmd.CommandText = queryString;
cmd.Parameters.AddWithValue("#Username", Username);
cmd.ExecuteNonQuery();
}
From SQL Injection point of view using parameters is usually safe (subject to what you do with those parameters in the SQL...). Your example is safe. How one adds the parameters makes no difference from the SQL Ibjection point of view, but makes a lot of difference from ADO.Net and SQL performance point of view. AddWithValue is an anti-pattern because of performance problems related to parameter type and size. In your example the #UserName will be a parameter of type NVARCHAR, which will likely make the WHERE Username=#UserName predicate unsarg-able (will not use an index on Username). The execution result would be dreadful.
A potential solution to the datatype conversion is to use the explicit Add method instead of AddWithValue, which takes the datatype as second parameter. More details on this here.
For more details I urge you to read How Data Access Code Affects Database Performance.
In Short parameters allow for type safe and length checks on the data. Enabling a defense against SQL injection, they do not prohibit SQL injection completely you still need to check your inputs.
SO Answer on similar topic.
Good article explaining how parameters do not prevent SQL injection 100%
SQL Injection Example (Taken from MSDN:)
Consider what happens when a user types the following string in the SSN text box, which is expecting a Social Security number of the form nnn-nn-nnnn.
' ; DROP DATABASE pubs --
Using the input, the application executes the following dynamic SQL statement or stored procedure, which internally executes a similar SQL statement.
// Use dynamic SQL
SqlDataAdapter myCommand = new SqlDataAdapter(
"SELECT au_lname, au_fname FROM authors WHERE au_id = '" +
SSN.Text + "'", myConnection);
// Use stored procedures
SqlDataAdapter myCommand = new SqlDataAdapter(
"LoginStoredProcedure '" +
SSN.Text + "'", myConnection);
The developer's intention was that when the code runs, it inserts the user's input and generates a SQL the following statement.
SELECT au_lname, au_fname FROM authors WHERE au_id = '172-32-9999'
However, the code inserts the user's malicious input and generates the following query.
SELECT au_lname, au_fname FROM authors WHERE au_id = ''; DROP DATABASE pubs --'
Common ways to avoid Injection attacks.
•Constrain and sanitize input data. Check for known good data by validating for type, length, format, and range.
•Use type-safe SQL parameters for data access. You can use these parameters with stored procedures or dynamically constructed SQL command strings. Parameter collections such as SqlParameterCollection provide type checking and length validation. If you use a parameters collection, input is treated as a literal value, and SQL Server does not treat it as executable code. An additional benefit of using a parameters collection is that you can enforce type and length checks. Values outside of the range trigger an exception. This is a good example of defense in depth.
•Use an account that has restricted permissions in the database. Ideally, you should only grant execute permissions to selected stored procedures in the database and provide no direct table access.
•Avoid disclosing database error information. In the event of database errors, make sure you do not disclose detailed error messages to the user.
if you do not use Parameterised queries with above command then it looks like :
string queryString="DELETE FROM dbo.SecurityAccess WHERE Username = '"+txtUserName.Text+"'";
in the above command username would be assigned whatever user enters in TextBox( ex: txtUserName).
if user wants to inject some behaviour( adding delete/update or whatever he wants to do) he can enter following in TextBox (txtUserName)
=> "'';delete * from users"
then the above command with given username value looks like this:
string queryString="DELETE FROM dbo.SecurityAccess WHERE Username = '';delete * from users";
finally the above command would delete all the records from the users table.
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" });
As the title says, if I'm using SQL parameters, ie
SQLCommand cmd = new SQLCommand("select * from users where username = #user and password = #pass limit 1", Cxn);
cmd.Parameters.Add("#user", SqlDbType.VarChar):
cmd.Parameters.Add("#pass", SqlDbType.VarChar):
Can I just enter the parameters value as the direct entry from the input?
cmd.Parameters["#user"].value = txtBxUserName.text;
cmd.Parameters["#pass"].value = txtBxPassword.text;
That's what seems to be suggested whenver you look for anything to do with escaping string etc, the end answer is to just let the parameter binding do it. But will that protect against injection attacks and the like? Or do you still need to perform some server side validation?
Coming from a heavily orientated PHP background it goes against every fibre of my body to directly enter text into a query :p
The example you've given is safe in terms of SQL Injection. The only potential SQL Injection problem with parameterized queries is if they address a proc which itself uses dynamic SQL.
Of course, you still have to think about XSS exploits whether you're parameterizing or not.
Yes, this is the safeties way to store data in database using .net. SQL parameter provide type checking and validation. Because they are treated as a literal value, not as an executable code, this prevents from sql injection.
Using parameters will escape out all special characters and prevent injection attacks. This is why parameters are the recommended method.