What would be the best way to stop SQL injection with a LIKE statement? So here is a example of the code:
string search = Server.HTMLDecode(userEnteredSearchText);
SqlCommand comm = new SqlCommand("SELECT Result WHERE (Keyword LIKE '%" + #search + "%') "
comm.Parameters.Add(new SqlParameter("search", search));
This is what I have been doing other sql statements and it seems like special characters such as ' and % can't break those statements, but I'm guessing with a LIKE statement you need to do a escape key or something?
The following looks a little cleaner to me.
string search = Server.HTMLDecode(userEnteredSearchText);
SqlCommand comm = new SqlCommand("SELECT Result WHERE (Keyword LIKE #search) "
comm.Parameters.Add(new SqlParameter("search", String.Format("%{0}%", search)));
Sorry the quotes are off. You do it precisely like you do with everything else, except that within the SQL you need to concatenate the %'s. Also, HTMLDecode is probably not doing you any good here at all, right? What if they want to search in the db for things that contain "&"
Search = userEnteredSearchText);
SqlCommand comm = new SqlCommand("SELECT Result WHERE Keyword LIKE '%' + #search + '%'");
comm.Parameters.Add(new SqlParameter("search", search));
So in your example, you were closing the SQL literal to put in #search, which is an invalid keyword or variable - you just need to leave that inside the SQL statement. Other DB's, you need to CONCAT the things together. But the bind variable will properly escape the stuff going to the driver.
Avoid single quote for sure in the parameters when you are sending a sql query to database.
Remove any special character present in the parameter in the c# code itself.
I would suggest avoid as many special character as possible.
Related
I want to insert multiple rows into my database, I tried to use parameters but I did something wrong.
In debug mode, the parameters do have values, but once the insert is done, I still have #compte, #mo, #userimp in my database instead of their values.
string INSERTDELAMORTPart2 = "'123'," + "'#compte'" + "," + "'#mo'" + "," + "'ubs'" + "," + "'2'" + "," + "'#userimp'" + "," + "'22.10.17'" + ",'";
OdbcCommand Query = new OdbcCommand(INSERTDELAMORTPart2, InfoConnexion);
Query.Parameters.AddWithValue("#compte", _cb_Compte.SelectedItem);
Query.Parameters.AddWithValue("#mo", MondantResultat);
Query.Parameters.AddWithValue("#userimp", UserImp);
Query.ExecuteNonQuery();
I have tried Parameters.Add, and also Parameters["#name"].Value, but the result stays the same.
What am I doing wrong ?
EDIT :
I have an Oracle database and I need the single quote to insert my values.
I have tried to pass my whole INSERT string into a parameter but it doesn't work.
I'm about to give up and just replace the ' by '' even if it's a bad idea.
A few things.
If you are using Oracle, I highly recommend you use ODP.net or managed ODP.net, not ODBC. ODBC should work, but the native drivers will work more efficiently and will avoid any oddities you might with with the abstraction layer ODBC provides. Managed ODP.net has the additional advantage of not requiring an Oracle client be installed on the target machine
SQL Server (and other databases) use the "#" as a parameter, but Oracle uses the colon ":" instead. Some databases (like PostgreSQL) will take either. While the parameter in your SQL requires the colon, when you use assign the parameter in .NET you need to omit it. Again, this is an Oracle thing you won't find in other databases.
Your SQL doesn't appear to have any command in it... only values. Where is your "insert into?"
Especially with Oracle, you want to be explicit about your datatypes... so use Add instead of AddWithValue (which is actually an overload of Add in ODP.net). Alternatively, you can set the datatype later.
The converted code would look something like this:
string insert = "insert into my_table values (:COMPTE, :MO, :USERIMP)";
using (OracleCommand cmd = new OracleCommand(insert, Connection))
{
// no ":" in the parameter declarations
cmd.Parameters.Add(new OracleParameter("COMPTE", OracleDbType.Int32));
cmd.Parameters.Add(new OracleParameter("MO", OracleDbType.Varchar2));
cmd.Parameters.Add(new OracleParameter("USERIMP", OracleDbType.Varchar2));
cmd.Parameters[0].Value = 123;
cmd.Parameters[1].Value = "ubs";
cmd.Parameters[2].Value = "22.10.17";
cmd.ExecuteNonQuery();
}
I guessed at your datatypes -- make sure they match your DDL when you actually implement this, and if these aren't the only three columns, update your insert command appropriately.
If for some reason I misunderstood, and this is not Oracle, I still recommend use of the native driver rather than ODBC. When you use ODBC, you assume a lot about the target machine -- assumptions that may not turn out to be true.
The command should look something like this:
insert into t(compte, mo, userimp) -- of course the table and columns should be the right names
values (#compte, #mo, #userimp);
No single quotes are needed.
I would recommend against using AddWithValue(). Instead, be explicit about the types.
You have this:
string INSERTDELAMORTPart2 = "'123'," + "'#compte'" ...
Note the single quotes around the parameter names. They should not be there. You want this instead:
string INSERTDELAMORTPart2 = "'123'," + "#compte"
If I want to insert a statement which contains quotation mark, how is it possible ?
For Example I have a text box and I enter:
Future Swami Vivekananda’s grand father's name was "____" .
If you use properly parameterized statements, you shouldn't need to worry about it. Something like this (though please don't learn C# techniques from me):
string sql = #"UPDATE dbo.table SET col = #p1 WHERE ...;";
string myString = #"hello'foo""bar";
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#p1", SqlDbType.VarChar, 30).Value = myString;
(Though you really should be using stored procedures.)
If you are building your strings manually (which you really, really, really shouldn't be doing), you need to escape string delimiters by doubling them up:
INSERT dbo.tbl(col) VALUES('hello''foo"bar');
Use a parameterized query - then quotes don't matter at all. Also - your database doesn't get taken over by SQL injection - so win/win really.
You can double up the quote:
INSERT INTO table
VALUES ('Future Swami Vivekananda''s grand father''s name was "____"')
option 1: in this values are inserted using parameters
string insertstr = "INSERT INTO table_name(eid, eName, Dept) " +
"VALUES(#eid, #eName, #dept)";
SqlCommand cmd = new SqlCommand(insertstr, con);
cmd.Parameters.Add("#eid", SqlDbType.Int).Value = Convert.ToInt32(textBox1.Text);
cmd.Parameters.Add("#ename", SqlDbType.VarChar, 50).Value = textBox2.Text.ToString();
cmd.Parameters.Add("#dept", SqlDbType.VarChar, 100).Value = textBox3.Text.ToString();
Option 2:
SqlCommand cmd = new SqlCommand("INSERT INTO table_name(eid,eName,Dept) values('"+ textBox1.Text +"','"+ textBox2.Text +"','"+ Textbox3.Text +"'", con);
cmd.ExecuteNonQuery();
Most of the projects i had seen the 1st option... what is the use of passing values using parameters?? any advantages by passing values using parameters?? your suggestion plz..
You don't have to care about quoting special characters. If you forget to quote a SQL-Injection attack is possible.
If you use Option 2 and one enters the following into Textbox3
'); DELETE * FROM table_name; --
the following SQL statements are excecuted:
INSERT INTO table_name(eid,eName,Dept) values ('value1','value2','');
DELETE * FROM table_name; -- ')
The second statement deletes every row from table_name. Instead of a delete statement any possible statement could be inserted there.
Several reasons:
You don't have to worry to escape special characters (like ') to avoid SQL errors or SQL injections (as explained by H-Man2).
You don't have to worry to transform C# types to SQL types. For instance:
If your NumberDecimalSeparator is equal to the comma , and you want to insert a Double value in your database, you normally have to replace the comma by a point. No need to worry about that with parameters.
No need to worry about DateTime formats neither.
...
I find also the code more readable and easier to maintain with parameters when your SQL queries start to have a great length.
You should NEVER use option 2.
This is very bad practise, and very open to SQL Injection.
Always stick with Option 1. This is the best option by far.
Read here for more information on SQL Injection:
http://en.wikipedia.org/wiki/SQL_injection
For example, this is the code that I am using:
String commandString = "UPDATE Members SET UserName = #newName , AdminLevel = #userLevel WHERE UserID = #userid";
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["sqlconnectionstring"].ConnectionString))
{
SqlCommand cmd = new SqlCommand(commandString, conn);
cmd.Parameters.Add("#newName", newName);
cmd.Parameters.Add("#userLevel", userLevel);
cmd.Parameters.Add("#userid", userid);
conn.Open();
cmd.ExecuteReader();
Reader.Close();
}
That code looks fine. Parameterisation is the way to go, as opposed to concatenating user-supplied values in an adhoc SQL statement which can open you up to sql injection attacks. This can also help with execution plan reuse.
The only thing I'd add, is I prefer to explicitly define the datatype and sizes of the parameters. For example, if you don't then, as an example, all string values will get passed in to the database as NVARCHAR instead of VARCHAR. Hence I like to be explicit.
It's safe against SQL injection because it's parameterized. Other security concerns, such as ensuring that #userid is not spoofed, are separate security concerns that should be dealt with in other layers of your application.
That's still a static query string. It's not really "dynamic" sql until you also build parts of the string on the fly — something like this:
var sql = "SELECT columns FROM Table WHERE 1=1";
if (!string.IsNullOrEmpty(txtName.Text)) sql += " AND Name LIKE '%' + #Name + '%'";
if (!string.IsNullOrEmpty(txtDesc.Text)) sql += " AND CONTAINS(DESCRIPTION, #description)";
But even so, this is still "safe" in the sql injection sense as long as you continue to use parameters for every part of the query that originates with user input.
i need to use the Characters ' in access query.
but if i write select Fname from MEN where Fnale = 'j'o' i get error
how to write the Characters '
thank's in advance
Try a backslash \' or two quotes ''.
This depends on your database. MySQL uses \' and Microsoft SQL and MS Access uses two quotes ''.
Single quotes can be escaped with two single quotes.
SELECT Fname FROM MEN WHERE Fnale = 'j''o'
For SQL Server:
var cmd = new SqlCommand("select fname from MEN where fnale = #query", myConnection);
cmd.Parameters.AddWithValue("#query", "j'o");
All solutions where you add your parameter to the sql string yourself are wrong (or at least high risk), because they are vulnarable for a SQL Injection Attack.
You mention "access query", for Microsoft Access / Ole use the following syntax:
var cmd = new OleDbCommand("select fname from MEN where fnale = ?", myConnection);
cmd.Parameters.AddWithValue("?", "j'o"); // Order does matter
I would use a literal string to avoid escaping everything
string query = #"select Fname from MEN where Fnale = 'jo'";
If you are escaping this with respect to SQL, then use another single quote to escape the quotes:
select Fname from MEN where Fnale = ''jo''
As others said, you can escape the quotes. But if you are sending that query from C#, then it's better to use parameters - that way all escaping is done for you, so you can't forget some special case where user input can still cause unwanted effects. (little bobby tables, anyone? :-) )
Try replacing ' with ''