I am very new to working with databases. Now I can write SELECT, UPDATE, DELETE, and INSERT commands. But I have seen many forums where we prefer to write:
SELECT empSalary from employee where salary = #salary
...instead of:
SELECT empSalary from employee where salary = txtSalary.Text
Why do we always prefer to use parameters and how would I use them?
I wanted to know the use and benefits of the first method. I have even heard of SQL injection but I don't fully understand it. I don't even know if SQL injection is related to my question.
Using parameters helps prevent SQL Injection attacks when the database is used in conjunction with a program interface such as a desktop program or web site.
In your example, a user can directly run SQL code on your database by crafting statements in txtSalary.
For example, if they were to write 0 OR 1=1, the executed SQL would be
SELECT empSalary from employee where salary = 0 or 1=1
whereby all empSalaries would be returned.
Further, a user could perform far worse commands against your database, including deleting it If they wrote 0; Drop Table employee:
SELECT empSalary from employee where salary = 0; Drop Table employee
The table employee would then be deleted.
In your case, it looks like you're using .NET. Using parameters is as easy as:
string sql = "SELECT empSalary from employee where salary = #salary";
using (SqlConnection connection = new SqlConnection(/* connection info */))
using (SqlCommand command = new SqlCommand(sql, connection))
{
var salaryParam = new SqlParameter("salary", SqlDbType.Money);
salaryParam.Value = txtMoney.Text;
command.Parameters.Add(salaryParam);
var results = command.ExecuteReader();
}
Dim sql As String = "SELECT empSalary from employee where salary = #salary"
Using connection As New SqlConnection("connectionString")
Using command As New SqlCommand(sql, connection)
Dim salaryParam = New SqlParameter("salary", SqlDbType.Money)
salaryParam.Value = txtMoney.Text
command.Parameters.Add(salaryParam)
Dim results = command.ExecuteReader()
End Using
End Using
Edit 2016-4-25:
As per George Stocker's comment, I changed the sample code to not use AddWithValue. Also, it is generally recommended that you wrap IDisposables in using statements.
You are right, this is related to SQL injection, which is a vulnerability that allows a malicioius user to execute arbitrary statements against your database. This old time favorite XKCD comic illustrates the concept:
In your example, if you just use:
var query = "SELECT empSalary from employee where salary = " + txtSalary.Text;
// and proceed to execute this query
You are open to SQL injection. For example, say someone enters txtSalary:
1; UPDATE employee SET salary = 9999999 WHERE empID = 10; --
1; DROP TABLE employee; --
// etc.
When you execute this query, it will perform a SELECT and an UPDATE or DROP, or whatever they wanted. The -- at the end simply comments out the rest of your query, which would be useful in the attack if you were concatenating anything after txtSalary.Text.
The correct way is to use parameterized queries, eg (C#):
SqlCommand query = new SqlCommand("SELECT empSalary FROM employee
WHERE salary = #sal;");
query.Parameters.AddWithValue("#sal", txtSalary.Text);
With that, you can safely execute the query.
For reference on how to avoid SQL injection in several other languages, check bobby-tables.com, a website maintained by a SO user.
In addition to other answers need to add that parameters not only helps prevent sql injection but can improve performance of queries. Sql server caching parameterized query plans and reuse them on repeated queries execution. If you not parameterized your query then sql server would compile new plan on each query(with some exclusion) execution if text of query would differ.
More information about query plan caching
Two years after my first go, I'm recidivating...
Why do we prefer parameters? SQL injection is obviously a big reason, but could it be that we're secretly longing to get back to SQL as a language. SQL in string literals is already a weird cultural practice, but at least you can copy and paste your request into management studio. SQL dynamically constructed with host language conditionals and control structures, when SQL has conditionals and control structures, is just level 0 barbarism. You have to run your app in debug, or with a trace, to see what SQL it generates.
Don't stop with just parameters. Go all the way and use QueryFirst (disclaimer: which I wrote). Your SQL lives in a .sql file. You edit it in the fabulous TSQL editor window, with syntax validation and Intellisense for your tables and columns. You can assign test data in the special comments section and click "play" to run your query right there in the window. Creating a parameter is as easy as putting "#myParam" in your SQL. Then, each time you save, QueryFirst generates the C# wrapper for your query. Your parameters pop up, strongly typed, as arguments to the Execute() methods. Your results are returned in an IEnumerable or List of strongly typed POCOs, the types generated from the actual schema returned by your query. If your query doesn't run, your app won't compile. If your db schema changes and your query runs but some columns disappear, the compile error points to the line in your code that tries to access the missing data. And there are numerous other advantages. Why would you want to access data any other way?
In Sql when any word contain # sign it means it is variable and we use this variable to set value in it and use it on number area on the same sql script because it is only restricted on the single script while you can declare lot of variables of same type and name on many script. We use this variable in stored procedure lot because stored procedure are pre-compiled queries and we can pass values in these variable from script, desktop and websites for further information read Declare Local Variable, Sql Stored Procedure and sql injections.
Also read Protect from sql injection it will guide how you can protect your database.
Hope it help you to understand also any question comment me.
Old post but wanted to ensure newcomers are aware of Stored procedures.
My 10¢ worth here is that if you are able to write your SQL statement as a stored procedure, that in my view is the optimum approach. I ALWAYS use stored procs and never loop through records in my main code. For Example: SQL Table > SQL Stored Procedures > IIS/Dot.NET > Class.
When you use stored procedures, you can restrict the user to EXECUTE permission only, thus reducing security risks.
Your stored procedure is inherently paramerised, and you can specify input and output parameters.
The stored procedure (if it returns data via SELECT statement) can be accessed and read in the exact same way as you would a regular SELECT statement in your code.
It also runs faster as it is compiled on the SQL Server.
Did I also mention you can do multiple steps, e.g. update a table, check values on another DB server, and then once finally finished, return data to the client, all on the same server, and no interaction with the client. So this is MUCH faster than coding this logic in your code.
Other answers cover why parameters are important, but there is a downside! In .net, there are several methods for creating parameters (Add, AddWithValue), but they all require you to worry, needlessly, about the parameter name, and they all reduce the readability of the SQL in the code. Right when you're trying to meditate on the SQL, you need to hunt around above or below to see what value has been used in the parameter.
I humbly claim my little SqlBuilder class is the most elegant way to write parameterized queries. Your code will look like this...
C#
var bldr = new SqlBuilder( myCommand );
bldr.Append("SELECT * FROM CUSTOMERS WHERE ID = ").Value(myId);
//or
bldr.Append("SELECT * FROM CUSTOMERS WHERE NAME LIKE ").FuzzyValue(myName);
myCommand.CommandText = bldr.ToString();
Your code will be shorter and much more readable. You don't even need extra lines, and, when you're reading back, you don't need to hunt around for the value of parameters. The class you need is here...
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
public class SqlBuilder
{
private StringBuilder _rq;
private SqlCommand _cmd;
private int _seq;
public SqlBuilder(SqlCommand cmd)
{
_rq = new StringBuilder();
_cmd = cmd;
_seq = 0;
}
public SqlBuilder Append(String str)
{
_rq.Append(str);
return this;
}
public SqlBuilder Value(Object value)
{
string paramName = "#SqlBuilderParam" + _seq++;
_rq.Append(paramName);
_cmd.Parameters.AddWithValue(paramName, value);
return this;
}
public SqlBuilder FuzzyValue(Object value)
{
string paramName = "#SqlBuilderParam" + _seq++;
_rq.Append("'%' + " + paramName + " + '%'");
_cmd.Parameters.AddWithValue(paramName, value);
return this;
}
public override string ToString()
{
return _rq.ToString();
}
}
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.
first off i have found several topics which are similar but do not quite answer all my questions.
my first question if i use code like this:
MySqlCommand cmd = new MySqlCommand("SELECT `productnummer`, `NAAM`, `TYPE` `OMSCHRIJVING`, `Product-ID`, `Barcode` FROM `orders`.`producten` where (`productnummer` like(#variable) or `naam` like #variable or `type` like #variable or `omschrijving` like #variable or `product-id` like #variable or `barcode` like #variable) "and `uit assortiment` = 0");
cmd.Parameters.Add(new MySqlParameter("#variable", '%' + textBox1.Text + '%'));
how can parameters be safe if i can define my sql variable with % which (for as far as i know is an sql syntax).
does this not mean that if a user would enter a % or * or something them selves it would work?
my 2nd question:
MySqlCommand cmd = new MySqlCommand("SELECT `user-id` FROM `orders`.`werknemers` WHERE username = #username and `password` = #password");
cmd.Parameters.Add(new MySqlParameter("#username", username));
cmd.Parameters.Add(new MySqlParameter("#password", password));
if i have a database with a table that contains usernames and passwords (hashes of passwords obviously).
my application has a textbox in which to type a username and a password by the user. The password will be hashed and this data will be send to the database as seen above.
if the database returns a user-id i know this user exists and i can use the user-id to communicate further, if it doesn't well obviously something was typed in wrong
is this a safe way to do this? or are there better ways?
in general it all comes down to this:
what is the safest way for communicating with a database in c#?
You need to look at the root problem in the query safety: non-parameterized queries present threats because the data that end-users plug into them as strings gets re-interpreted as code in a programming language (namely, a code in SQL). Parameterized queries stop that from happening: the interpretation ends with the declaration of a query parameter. Whatever gets plugged into that parameter as a value is interpreted as an ordinary sequence of characters. It never makes it into SQL interpreter (unless you make a grave mistake of using SQL's exec facility, which you should never do with data that comes close to anything entered by end-users).
As far as hashing passwords goes, no, what your code does is not safe. It is open to offline attacks, because your hash is not salted. But this is a subject of a separate answer.
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
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.