What's the safest way of generating SQL queries in C#, including cleansing user input so it's safe from injection? I'm looking to use a simple solution that doesn't need external libraries.
Use Sql Parameters:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlparameter(v=vs.80).aspx
Here's an example in C#
SqlCommand tCommand = new SqlCommand();
tCommand.Connection = new SqlConnection("YourConnectionString");
tCommand.CommandText = "UPDATE players SET name = #name, score = #score, active = #active WHERE jerseyNum = #jerseyNum";
tCommand.Parameters.Add(new SqlParameter("#name", System.Data.SqlDbType.VarChar).Value = "Smith, Steve");
tCommand.Parameters.Add(new SqlParameter("#score", System.Data.SqlDbType.Int).Value = "42");
tCommand.Parameters.Add(new SqlParameter("#active", System.Data.SqlDbType.Bit).Value = true);
tCommand.Parameters.Add(new SqlParameter("#jerseyNum", System.Data.SqlDbType.Int).Value = "99");
tCommand.ExecuteNonQuery();
In essence don't do this
SqlCommand command = new SqlCommand(MyConnection);
command.CommandText = "Select * From MyTable Where MyColumn = '" + TextBox1.Text + "'"
...
do
SqlCommand command = new SqlCommand(MyConnection);
command.CommandText = "Select * From MyTable Where MyColumn = #MyValue";
command.Parameters.AddWithValue("MyValue",TextBox1.Text);
...
Basically never build your sql command directly from user input.
If you use an ORM, such as EntityFrameworks / POCO all queries are done in the latter form.
The first rule of thumb is to make sure you use parameterized queries/commands. Basically don't dynamically build a sql string that includes something that the user has input into the page.
If you use on ORM (EF, L2S, Nhib), this is typically handled in most cases because most all of them run parameterized queries.
Parametrize your queries.
In case if you build some TSQL which builds some other dynamic TSQL - then use some described technique
What does "parametrizing means?
See, not use something like this:
sqlCommand.CommandText = "select * from mytable where id = "+someVariable;
use this:
sqlCommand.CommandText = "select * from mytable where id = #id";
sqlCommand.Parameters.AddWithValue("#id", someVariable);
Make use of Parametrized Queries.
Simple Example.
var sql = "SELECT * FROM MyTable WHERE MyColumn = #Param1";
using (var connection = new SqlConnection("..."))
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("#Param1", param1Value);
return command.ExecuteReader();
}
More Detailed Example.
protected void btnGoodAddShipper_Click(object sender, EventArgs e)
{
string connStr = c
"Server=(local);Database=Northwind;Integrated Security=SSPI";
// this is good because all input becomes a
// parameter and not part of the SQL statement
string cmdStr =
"insert into Shippers (CompanyName, Phone) values (" +
"#CompanyName, #Phone)";
using (SqlConnection conn = new SqlConnection(connStr))
using (SqlCommand cmd = new SqlCommand(cmdStr, conn))
{
// add parameters
cmd.Parameters.AddWithValue
("#CompanyName", txtCompanyName.Text);
cmd.Parameters.AddWithValue("#Phone", txtPhone.Text);
conn.Open();
cmd.ExecuteNonQuery();
}
}
Using DBML and LINQ to handle it for you. Many people have worked on those to ensure those issues are well mitigated.
And if not than at least parametrize your queries.
A proper name for DBML is linq2sql or an advanced version is called entity framework. These technologies are provided by Microsoft and well integrated with visual studio. Does not require additional libraries.
Pretty stable products..
Related
I was wondering if it is possible for the update button to save the changes made in the table. I wrote this code but I have no idea how it could possibly work
This is the code i wrote for the update button:
string conString = "Data Source=MIRANDA-PC;Initial Catalog=Futebol do Rosa;Integrated Security=True";
SqlConnection con = new SqlConnection(conString);
string selectSql = "Update Players$ set Player Name='" + dataGridView2.Text + "";
SqlCommand cmd = new SqlCommand(selectSql, con);
con.Open();
This is the table I want to update the values in:
Well, you just need to execute your query with ExecuteNonQuery.
But more important, you should always use parameterized queries. This kind of string concatenations are open for SQL Injection attacks.
Also use using statement to dispose your SqlConnection and SqlCommand.
And if your table or column names more than one word, you need to use them with [] as [Player Name]. And honestly, it is a little bit weird to use $ sign in a table name.
using(SqlConnection con = new SqlConnection(conString))
using(SqlCommand cmd = con.CreateCommand())
{
cmd.CommandText = "Update Players$ set [Player Name] = #name";
cmd.Parameters.Add("#name", SqlDbType.NVarChar, 16).Value = dataGridView2.Text;
con.Open();
cmd.ExecuteNonQuery();
}
You have to execute your SQL query with your db object.
dbinstance.ExecuteSqlCommand(string sqlcommand, object[] params);
This method is both for DDL and DML.
you can also use ExecuteNonQuery method.
cmd.CommandText = "Update Players$ set [Player Name] = #Playername";
cmd.Parameters.Add("#Playername", SqlDbType.NVarChar, 16).Value = dataGridView2.Text;
con.Open();
cmd.ExecuteNonQuery();
The best solution (if possible) to to convert your DAL (Data Access Layer) to Entity-framework based, instead of writing your own SQL queries. This is safe-by-design and never is vulnerable to SQL Injection of any kind.
Here is some mockup code:
using (AppEntities currDb = new AppEntities)
{
Players PlayerToEdit =
from player in currDb.Players
where player.PlayerID == lngPlayerID
select player.First();
PlayerToEdit.PlayerName = dataGridView2.Text;
currDb.SaveChanges();
}
You can read about it some more here:
https://msdn.microsoft.com/en-us/data/ef.aspx
I want to modify a constraint on a SQL Server table from C# code. Is it possible to do?
Please help.
Here is a sample code for update that I use.
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "UPDATE Student(LastName, FirstName, Address, City)
VALUES(#ln, #fn, #add, #cit) WHERE LastName='" + lastName + "' AND FirstName='" + firstName+"'";
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
var removeConstraint = "ALTER TABLE Customer DROP CONSTRAINT Con_First;";
var createConstraint = "ALTER TABLE Customer ADD CONSTRAINT Con_First UNIQUE (Address);";
var removeConstraintCmd = new SqlCommand(removeConstraint, conn);
removeConstraintCmd.ExecuteNonQuery();
var createConstraintCmd = new SqlCommand(createConstraint, conn);
createConstraintCmd.ExecuteNonQuery();
NOTE: conn is your connection
The script strings (top two variables) will be what you need to change but, in summary, you drop the constrain then recreate it.
As a side note, I'd be curious to see why you want to do this. You may have problems in your overall approach as this is not something typically done from ADO .net (depending on your scenario of course).
I'm trying to make an ATM Simulator. When I want to add some money in my account which is registered in SQL Server, I don't know how to add a value over the old value.
My SQL Table is like this:
Name | Surname | Pin | Money
When i want to add Money from textBox in the Money column I don't know how.
Code:
con.Open();
string connString = "";
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select * from Useri where Pin='" + textBox1_Pin.Text + "' ";
var reader = cmd.ExecuteReader();
double balanciFillestar = Convert.ToDouble(reader[3]);
double balanciRi = balanciFillestar + double.Parse(textBox_shuma.Text);
cmd.CommandText = "update Useri set Shuma =" + balanciRi + "";
cmd.ExecuteNonQuery();
con.Close();
The most immediate need would be to filter the update statement, so instead of this:
cmd.CommandText = "update Useri set Shuma =" + balanciRi + "";
you really need this:
cmd.CommandText = "UPDATE Useri SET Shuma = #Shuma WHERE Pin = #Pin";
But, before you can do that we really need to refactor it all.
var selectSql = "SELECT Shuma FROM Useri WHERE Pin = #Pin";
var updateSql = "UPDATE Useri SET Shuma = #Shuma WHERE Pin = #Pin";
using (SqlConnection c = new SqlConnection(cString))
{
c.Open();
double balanciFillestar;
using (SqlCommand cmd = new SqlCommand(selectSql, c))
{
cmd.Parameters.AddWithValue("#Pin", textBox1_Pin.Text);
balanciFillestar = Convert.ToDouble(cmd.ExecuteScalar());
}
double balanciRi = balanciFillestar + double.Parse(textBox_shuma.Text);
using (SqlCommand cmd = new SqlCommand(updateSql, c))
{
cmd.Parameters.AddWithValue("#Shuma", balanciRi);
cmd.Parameters.AddWithValue("#Pin", textBox1_Pin.Text);
cmd.ExecuteNonQuery();
}
}
There are a number of things I'm doing here that you'll want to learn from:
The SQL statements are parameterized.
The SqlConnection is not shared.
The ADO.NET objects are wrapped in a using statement.
A SqlDataReader isn't used to get a single value from a single row.
All of these things, with the exception of #4, are equally important.
Point #1 ensures that you're protecting yourself from SQL Injection attacks.
Point #2 is quite simply the only viable way to use the class. It's meant to be constructed, opened, used, and disposed.
Point #3 ensures that the Dispose method is called on all of the objects. This is extremely important with these classes because they implement IDisposable. They do because they handle unmanaged resources (i.e. a connection to a SQL server).
Point #4 is really just an optimization. Data readers are meant for reading very large data sets, one row at a time, to gain performance and resource management. Likewise the data reader is actually left open until it is closed or disposed. Generally speaking there are almost always better API's to use than a data reader unless using it for their express purpose.
Your code is vulnerable against SQL injection. Please consider this and use parameterized query.
string ps= "update Useri set Shuma = Shuma + #shuma WHERE Pin= #pin";
SqlCommand cmd = new SqlCommand(ps, c);
cmd.Parameters.AddWithValue("#shuma", textBox_shuma.Text);
cmd.Parameters.AddWithValue("#pin", textBox1_Pin.Text);
I'm creating an assembly in C# for MS SQL 2005. This assembly creates a stored procedure and runs a dynamic query based on parameters passed into the stored procedure.
Is there a simple function in C# to prevent SQL injection?
For example
string myQuery = "SELECT * FROM dbo.MyTable WHERE lastName = '" + injectionCheck(arg1) + "'";
This question was answered for the standard query... but in situations where there is no way around building a truely dynamic query what can I use in C# for injection checking?
For example, these probably wont work:
using #dbName;
SELECT * FROM #table
OPEN SYMMETRIC KEY #keyName
etc
Use bound parameters:
SqlCommand cmd = new SqlCommand(myQuery, conn);
cmd.Parameters.Add("#lastname", SqlDbType.NVarChar, 10, lastName);
Use parameters ....
(This has been posted often already)
string myQuery = "SELECT * FROM myTable WHERE lastname = #p_name";
SqlCommand cmd = new SqlCommand();
cmd.CommandText = myQuery;
cmd.Parameters.Add ("#p_name", SqlDbType.Varchar).Value = "melp";
I am using C# to write a method that returns the following information about a table:
column names, column types, column sizes, foreign keys.
Can someone point me in the right direction on how to accomplish this ?
This really depends on how you communicate with your database. If you are using LinqToSQL or another similar ORM this would be pretty easy but if you want to get these values via a query I'd suggest you use the INFORMATION_SCHEMA views as these are fast and easy to query.
e.g.
select * from information_schema.columns where table_name = 'mytable'
To get the FK and Schema you should be able to use:
DA.FillSchema()
DS.Table("Name").PrimaryKey
OR calling sp_fkey using the method demonstrated below
Code Snippet from AND Another Link
private void LoanSchema()
{
private List<String> tablesList = new List<String>();
private Dictionary<String, String> columnsDictionary = new Dictionary<String, String>();
string connectionString = "Integrated Security=SSPI;" +
"Persist Security Info = False;Initial Catalog=Northwind;" +
"Data Source = localhost";
SqlConnection connection = new SqlConnection();
connection.ConnectionString = connectionString;
connection.Open();
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = "exec sp_tables";
command.CommandType = CommandType.Text;
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
tablesList.Add(reader["TABLE_NAME"].ToString());
}
reader.Close();
command.CommandText = "exec sp_columns #table_name = '" +
tablesList[0] + "'";
command.CommandType = CommandType.Text;
reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
columnsDictionary.Add(reader["COLUMN_NAME"].ToString(), reader["TYPE_NAME"].ToString());
}
}
You can use the SqlDataAdapter.FillSchema() method.
Alternatively you can use the SqlDataAdapter.Fill() method after setting the MissingSchemaAction property of the SqlDataAdapter to AddWithKey. But if you only want the schema you must ensure that your query returns no rows. This can be accomplished by adding a statement like WHERE 1=2 to your query.
If you are using MS SQL Server then You should definately have a look at SMO namespace (server management objects).
There are objects which You can use in .net responsible for all kinds of things in a database (including but not limited to tables, columns, constraints etc.)
I think you need the System.Data.DataTable class:
http://msdn.microsoft.com/en-us/library/system.data.datatable.aspx