Protect my app from SQL Injection [duplicate] - c#

This question already has answers here:
How can prepared statements protect from SQL injection attacks?
(10 answers)
Closed 4 years ago.
For now I execute a search in database and display the result with
string keyWord = textBoxSearch.Text.ToString();
using (SqlConnection con = new SqlConnection(conString))
{
try
{
con.Open();
if (con.State == ConnectionState.Open)
{
using (SqlCommand cmd = new SqlCommand("SELECT articleCode, articleName FROM Article WHERE articleName LIKE '" + keyWord + "%'", con))
{
// Put search result in dataGrid
}
}
}
}
Now following SqlCommand.Parameters example I should do something like
string cmdQuery = "SELECT articleCode, articleName from Article WHERE articleName LIKE #articleName'";
using (SqlConnection con = new SqlConnection(conString))
{
using (SqlCommand cmd = new SqlCommand(cmdQuery, con))
{
cmd.Parameters.Add("#articleName", SqlDbType.NVarChar);
cmd.Parameters["#articleName"].Value = textBoxSearch.Text;
try
{
// Put search result in dataGrid
}
}
}
But I don't really see how different this is because I still have to use the raw textBoxSearch.Text value.
Am I doing this right ?

To protect a web site from SQL injection, you can use SQL parameters.
SQL parameters are values that are added to an SQL query at execution time, in a controlled manner.
Example:
txtUserId = getRequestString("UserId");
sql = "SELECT * FROM Customers WHERE CustomerId = #0";
command = new SqlCommand(sql);
command.Parameters.AddWithValue("#0",txtUserID);
command.ExecuteReader();
The SQL engine checks each parameter to ensure that it is correct for its column and are treated literally, and not as part of the SQL to be executed.
View this for more details.
And yes, you can still use the textbox to take in value.

Related

Struggling with Parameterized Insert Query [duplicate]

This question already has an answer here:
How to use OdbcParameter for MySQL?
(1 answer)
Closed 3 years ago.
I'm really struggling with creating a parameterized insert query in C# using OdbcConnection and MySQL. If I use string concatenation in the SQL statement it works fine. However, I need to accept user input from a textbox and this is vulnerable to SQL injection.
When I try to setup the parameterized query the command sorta works. A record is inserted into the database so I know the connection is being made and a record is able to be inserted. The issue is all the inserted field values are null as if it's not reading the parameters.
The following code works:
public static void Insert(string connectionString, Vendor vendor)
{
using (OdbcConnection connection = new OdbcConnection(connectionString))
{
string SQL = "INSERT INTO tbl_vendor (name) VALUES (\"" + vendor.Name + "\")";
using (OdbcCommand command = new OdbcCommand(SQL, connection))
{
connection.Open();
command.ExecuteNonQuery();
}
}
}
The following code inserts an empty record:
public static void Insert(string connectionString, Vendor vendor)
{
using (OdbcConnection connection = new OdbcConnection(connectionString))
{
string SQL = "INSERT INTO tbl_vendor (name) VALUES (#name)";
using (OdbcCommand command = new OdbcCommand(SQL, connection))
{
OdbcParameter parameter = new OdbcParameter("#name", vendor.Name);
command.Parameters.Add(parameter)
connection.Open();
command.ExecuteNonQuery();
}
}
}
I've tried a million different variations of the above code. They all seem to work but each time they only insert an empty record. I'm probably missing something obvious and making things more complicated than they need to be but what am I doing wrong?
Test specifying the dataType:
OdbcParameter parameter = new OdbcParameter("#name", OdbcType.VarChar);
parameter.Value = vendor.Name;
command.Parameters.Add(parameter);

Error with SQLDataReader

C#, Razor
my code is:
#using (SqlConnection Praktikum2 = new SqlConnection("Data Source=Mark\\SQLEXPRESS;Initial Catalog=Connection;Integrated Security=True"))
{
using(connection)
{
SqlCommand command = new SqlCommand("SELECT KategoryID FROM Kategory WHERE Name = " + Request.Params["kategory"]);
connection.Open();
SqlDataReader reader = command.ExecuteReader(); //ERROR!!!
while (reader.Read())
{
string ID = reader["KategorieID"].ToString() ;
Console.WriteLine("ID = {0}", ID);
}
reader.Close();
};
}
i get an error that there's a wrong syntax near "=".
how can i solve this?
The problem is caused by the missing quotes around the value passed for your search. You could add a set of single quote before and after the value obtained by the Request but that would be a bigger error and the source of a problem called Sql Injection.
The only way to handle this is to use a parameter query
SqlCommand command = new SqlCommand(#"SELECT KategoryID FROM Kategory
WHERE Name = #name", connection);
command.Parameters.Add("#name", SqlDbType.NVarChar).Value = Request.Params["kategory"];
Also, as noted in another answer, your code seems to not have associated the connection to the command, I think that it is just a typo here because the error message in that case would be 'need an open connection'
You forgot to assign the connection to the command. So when you call ExecuteReader(), it does not know on which connection it should be executed.
You can assign the connection like this:
SqlCommand command = new SqlCommand(
"SELECT KategoryID FROM Kategory WHERE Name = " + Request.Params["kategory"],
connection); // provide connection as second parameter!
or use connection.CreateCommand() to create your command.
Second, you forgot the quotation marks around your string:
"SELECT KategoryID FROM Kategory WHERE Name = '" + Request.Params["kategory"] + "'"
but inserting user data directly into your query opens your code to SQL Injection. Please use parameterized queries instead.
If your kategory column is not of integer data type then you need to surround your value with (') i.e single quote characters
Then your query will be like
SqlCommand command = new SqlCommand("SELECT KategoryID FROM Kategory WHERE Name ='" + Request.Params["kategory"] + "'");
The exception is caused by how you are creating your sql statement. The fix should not be correcting the syntax but using parameters instead. This will prevent sql injection attacks.
Also
You really should not be writting sql in your views, do it in your controller method instead and return the result in the Model to be used in your view. Better yet, abstract it to a different layer and call that layer from your controller. This has to do with SoS (Separation of Concerns), your code will very difficult to maintain if you just write everything into your views.
Wrap your connections, commands, and readers in using blocks.
Modified Code
#{
using(SqlConnection Praktikum2 = new SqlConnection("Data Source=Mark\\SQLEXPRESS;Initial Catalog=Connection;Integrated Security=True"))
using(SqlCommand command = new SqlCommand("SELECT KategoryID FROM Kategory WHERE Name = #name", Praktikum2))
{
command.Parameters.Add(new SqlParameter("#name", SqlDbType.VarChar){ Value = Request.Params["kategory"]});
connection.Open();
using(SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
string ID = reader["KategorieID"].ToString() ;
Console.WriteLine("ID = {0}", ID);
}
}
}
}

How to execute query SQL with LIKE when i have spaces in the string

I created a database in Microsoft Access 2007 with the stock products of a company using an application buit in C # . I have a form to search for products by reference in the database but I am not able to obtain query results. The problem is that the column with the reference product has various spaces in the reference name:
Column product reference in the database
This is the code that I have to perform this query:
private void Ref_btn_Click(object sender, EventArgs e)
{
string connStr = (#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Stock.accdb");
string query = "Select * from product where product_ref like '%' + textBox_ref.Text + '%'";
using (OleDbConnection conn = new OleDbConnection(connStr))
{
using (OleDbDataAdapter adapter = new OleDbDataAdapter(query, conn))
{
DataSet ds = new DataSet();
adapter.Fill(ds);
dataGrid_stock.DataSource = ds.Tables[0];
}
}
}
What I want is to introduce for example in the textbox: "VDS" or "NT" and the query return "VDS 15P M X" and "NIP FIN NT LL" respectively.
thanks in advance,
Your query looks fine to me, I would only add a .Trim() to the end of textBox_ref.Text to prevent spaces from appearing between the search term and the % sign.
Your query has "wrong" quotes. Try this:
string query = "Select * from product where product_ref like '%" + textBox_ref.Text + "%'";
Here's a proper way to execute SQL statement safely:
string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Stock.accdb";
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand(
"SELECT * FROM product WHERE product_ref LIKE '%#value%'", connection))
{
command.Parameters.Add(new SqlParameter("value", textBox_ref.Text.Trim()));
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
// Do whatever you want to do with the queried data
}
}
}
This snippet is ideal for preventing SQL injections. It uses so called parameterized queries to avoid security issues. Futhermore, it manages to close your database connection after the code is executed by itself.
string.Trim() erases leading or heading whitespaces. This prevents unexpected mistakes.

How do I retrieve the result of an ADO.NET SqlCommand?

Ok either I'm really tired or really thick at the moment, but I can't seem to find the answer for this
I'm using ASP.NET and I want to find the amount of rows in my table.
I know this is the SQL code: select count(*) from topics, but how the HECK do I get that to display as a number?
All I want to do is run that code and if it = 0 display one thing but if it's more than 0 display something else. Help please?
This is what I have so far
string selectTopics = "select count(*) from topics";
// Define the ADO.NET Objects
SqlConnection con = new SqlConnection(connectionString);
SqlCommand topiccmd = new SqlCommand(selectTopics, con);
if (topiccmd == 0)
{
noTopics.Visible = true;
topics.Visible = false;
}
but I know I'm missing something seriously wrong. I've been searching for ages but can't find anything.
PHP is so much easier. :)
Note that you must open the connection and execute the command before you can access the result of the SQL query. ExecuteScalar returns a single result value (different methods must be used if your query will return an multiple columns and / or multiple rows).
Notice the use of the using construct, which will safely close and dispose of the connection.
string selectTopics = "select count(*) from topics";
// Define the ADO.NET Objects
using (SqlConnection con = new SqlConnection(connectionString))
{
SqlCommand topiccmd = new SqlCommand(selectTopics, con);
con.Open();
int numrows = (int)topiccmd.ExecuteScalar();
if (numrows == 0)
{
noTopics.Visible = true;
topics.Visible = false;
}
}
ExecuteScalar is what you're looking for. (method of SqlCommand)
Btw, stick with C#, there's no way PHP is easier. It's just familiar.
You need to open the connection
This might work :
SqlConnection sqlConnection1 = new SqlConnection("Your Connection String");
SqlCommand cmd = new SqlCommand();
SqlDataReader reader;
cmd.CommandText = "select count(*) from topics";
cmd.CommandType = CommandType.Text;
cmd.Connection = sqlConnection;
sqlConnection1.Open();
reader = cmd.ExecuteReader();
// Data is accessible through the DataReader object here.
sqlConnection1.Close();
Similar Question: C# 'select count' sql command incorrectly returns zero rows from sql server

Best Pratice on a quick SQL read from the DB in Sharepoint for a settings value

I have the following code that I am using to pick up some quick settings for a small custom control that's used sparilingly each month.
I am worried that this isn't the best and quickest approach that will use the least resources.
Can I get someone to evaluate my statements and suggust improvemnts?
public String getSettingVariable(string keyName)
{
var keyValue = String.Empty;
SPSecurity.RunWithElevatedPrivileges(delegate
{
string strConn = ConfigurationManager.ConnectionStrings["IntFTRDB"].ConnectionString;
using (SqlConnection sqlConn = new SqlConnection(strConn))
{
if (sqlConn != null || sqlConn.State != ConnectionState.Open) sqlConn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlConn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "Select distinct Value where Name = #name";
cmd.Parameters.Add("#name", SqlDbType.NVarChar);
cmd.Parameters["#name"].Value = keyName;
keyValue = (String)cmd.ExecuteScalar();
}
});
return keyValue;
}
How many sql calls do you have in your application? If just one or few, then the approach you are using is fine. If your application plans on making several (100s) of calls into the database, then a more elegant solution would be need like building out a data access layer or using an ORM.
The use of using to automatically dispose of the connection and a parametized sql call is perfectly acceptable.

Categories

Resources