Is this code safe from SQL injections? (and why) - c#

Is this code safe from SQL injections? Why?
public void AddPlayer(string username)
{
var query = "INSERT INTO dbo.Player(Username, RegisterDate) VALUES(#Username, #RegisterDate)";
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(query, connection))
{
command.Parameters.AddWithValue("#Username", username);
command.Parameters.AddWithValue("#RegisterDate", DateTime.Now);
command.Connection.Open();
command.ExecuteNonQuery();
}
}
public DateTime GetRegisterDate(string username)
{
var query = "SELECT RegisterDate FROM dbo.Player WHERE Username = #Username";
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(query, connection))
{
command.Parameters.AddWithValue("#Username", username);
command.Connection.Open();
return (DateTime)command.ExecuteScalar();
}
}
EDIT: Could injection-safe equivalent code be written using a stored procedure? If so, what the stored procedure would be like?

Yes, It looks safe.
Because it uses parameters.
You run a risk of SQL-injection when you create queries like
baseQueryText + " WHERE Username =" + TextBox.Text;
Reguarding the Edit: When you use a Stored Procedure you always use parameters so they are safe too. No special effort required, but you still could/should filter incoming data.

Yes. You are using parameterized queries, which are in general considered safe from SQL injection.
You may still want to consider filtering your inputs anyway.

Yes, all the non-static data is being fed in via bound parameters.

Related

C# multiple SQL select statements single method

I have a task to develop a console application that is a recon of values from a few tables in the DB. I have all the queries that I need for each value that is required and understand the logic on how the values will interact. The challenge I have is the best method to retrieve and store these values.
I have researched and successfully been able to create the static method to retrieve a single value from a single SQL query but I'm curious about the best method:
Create multiple methods to retrieve each value (upwards of 15 different select statements) summarised below (not complete code)
static double total1(int arg)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command1 = new SqlCommand(commandText1, connection));
return(response);
}
}
static double total2(int arg)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
SqlCommand command2 = new SqlCommand(commandText2, connection));
return(response);
}
}
Try to combine all select statements in a single method (I've been unsuccessful here) summarised below (not complete code)
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command1 = new SqlCommand(commandText1, connection))
{
}
using (SqlCommand command2 = new SqlCommand(commandText2, connection))
{
}
// etc
}
Create stored procedures in SQL and execute them and pass the parameters via the c# console app
I think method 1 is going to be taxing on the server as it would require the connection to open and close multiple times (although I don't know if that's as big a issue as I think it is). Method 2 seems more reasonable although I've followed the concepts here and I get stuck when trying to get the output of the commands (I'm using return). Method 3 seems smarter to me although I'd still be in a position where I need to choose between methods 1 & 2 to execute the SP's.
I would really appreciate advice and guidance here, I'm new to C# so this is a steep learning curve when tutorials don't cover the sort of thing (or at least I can't define my problem properly)
string query = "SELECT * FROM table1;";
query += "SELECT * FROM table2";
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand(query))
{
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataSet ds = new DataSet())
{
sda.Fill(ds);
}
}
}
}
I've recently seen that this question is still being viewed so I'll post the solution for anyone who is just starting off developing and encounters a similar challenge.
The most suitable solution was to create a stored procedure, pass each unique argument to it and return all the relevant data in a single response to the application. A custom model was defined for this output and the application logic adapted accordingly. The result is a longer running single call to the database as opposed to multiple individual ones.
Using the format from the question, the solution was:
C# code
static NewModel AllTotals(int arg1, int arg2)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
var commandText = "TheStoredProcName";
SqlCommand command = new SqlCommand(commandText, connection));
command.CommandType = System.Data.CommandType.StoredProcedure;
Cmd.Parameters.AddWithValue("#arg1", arg1);
Cmd.Parameters.AddWithValue("#arg1", arg2);
using (SqlDataReader dr = Cmd.ExecuteReader())
{
while (dr.Read())
{
var response = new NewModel(){
Value1 = Convert.ToDecimal(dr["value1"]),
Value2 = Convert.ToDecimal(dr["value2"]),
};
return(response);
}
}
}
return null;
}
SQL Stored Proc
CREATE PROCEDURE [dbo].[TheStoredProcName]
#arg1 int,
#arg2 int
AS
DECLARE #value1 decimal(18,6) = ISNULL((--QUERY TO GET VALUE1),0)
DECLARE #value2 decimal(18,6) = ISNULL((--QUERY TO GET VALUE2),0)
-- select the variables into a result set for the application
SELECT #value1 as [value1], #value2 as [value2]

Connecting to a Server

Trying to improve my C# to SQL skills... Currently I am using this bit of code to pull data from our application server. I have two different DBA's telling me two other ways to write this, just trying to figure out if this should be improved on or changed. If so, I would really appreciate some kind of examples.
FYI: This code...
db.con(user.Authority)
...Is essentially a 'new sqlconnection' code.
DataTable dtInfo = new DataTable("SomeInfo");
using (SqlConnection con = db.con(user.Authority))
{
string command = "SOME SQL STATEMENT;";
using (SqlCommand cmd = new SqlCommand(command,con))
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#Param", sqlDbType).Value = Param;
con.Open();
cmd.ExecuteNonQuery();
**********
*** OR ***
**********
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue("#Param", sqlDbType).Value = Param;
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dtInfo );
}
}
}
So, if I'm understanding the provided information, this is my best route?
using (SqlConnection con = db.con(user.Authority))
{
string command = "SELECT [TBL_EMPLOYEE].[ACTIVE_DIRECTORY] FROM [TBL_EMPLOYEE];";
using (SqlCommand cmd = new SqlCommand(command, con))
{
con.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
MessageBox.Show(reader["ACTIVE_DIRECTORY"].ToString());
}
}
}
And one last thing... This should prevent the need for
cmd.Dispose();
etc...
The code would depend on the specific query. If the query retrieves rows of data (as a SELECT does), then you would go the da.Fill() route. If it's a query that just makes a change to the database (such as INSERT, UPDATE, or DELETE), then you would use ExecuteNonQuery().
I would not use the SqlDataAdapter version. The version that uses the SqlCommand object and the SqlDataReader will perform better, and allows more insight into the actual data being returned.
// Assumes the following sql:
// SELECT foo, bar FROM baz
// error checking left out for simplicity
var list = new List<SomeClass>();
using(var reader = cmd.ExecuteReader()) {
while(reader.Read()) {
list.Add(new SomeClass {
// NOTE: you can see the columns that the c# is referencing
// and compare them to the sql statement being executed
Foo = (string)reader["foo"],
Bar = (string)reader["bar"]
});
}
}
Later as your level of experiance increases you will be able to use other features of the SqlCommand and SqlDataReader classes in order to ensure that the code executes as quickly as possible. If you start using the SqlDataAdapter route, you will eventually have to relearn how to do the exact same things you have already been doing because the SqlCommand and SqlDataReader have operations that do not exist elsewhere in .NET.
ExecuteNonQuery returns the number of rows effected.
A DataTable is not an efficient way to retrieve that number.
int rowsRet = cmd.ExecuteNonQuery();
SqlCommand.ExecuteNonQuery Method

Handle optional parameters when I call a stored procedure

Problem statement.
Basically I get 3 - 50 parameters that come back from a web service as a NVP array I then need to loop over them create the SQL command parameters for each and call the stored procedure. Is there a more efficient way to handle it than the approach below?
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand cm = connection.CreateCommand())
{
cm.CommandText = "MySproc";
cm.CommandType = CommandType.StoredProcedure;
foreach (var field in row)
{
cm.Parameters.AddWithValue("#" + field.Key.ToString(), field.Value.ToString());
}
cm.ExecuteNonQuery();
}
}
I personally use the ISNULL or COALESCE in the WHERE clause of the stored procedure. Unless your looking to do it inside your c#...
http://blogs.x2line.com/al/archive/2004/03/01/189.aspx

Refactor sql query from source code

I have a method which contains a very big sql query directly in the .CS file. What would the recommended refactoring method be?
You could put the large complex SQL query into a SQL View or Stored Procedure, and just use that in the code.
You should use stored procedure
string commandText = "SP_Your_Sp_Name";
using (SqlConnection objSqlConnection = Connection)
{
using (SqlCommand cmd = new SqlCommand(commandText, objSqlConnection))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("#Parameter_Name", value));
if (cmd.Connection.State != ConnectionState.Open)
{
cmd.Connection.Open();
}
result = (string)cmd.ExecuteScalar();
}
}
Use a stored procedure.
In this case the query execution will be faster when the execution plan is stored in the cache.

Use parametrized sql queries when SQLCommand used in separate class

I am interesting to add parametrize sql queries in my ASP.net application. I have seen some good articles regarding Avoid SQL Injection.
string sql = string.Format("INSERT INTO [UserData] (Username, Password, Role, Membership, DateOfReg) VALUES (#Username, #Password, #Role, #Membership, #DateOfReg)");
SqlCommand cmd = new SqlCommand(sql, conn);
try
{
cmd.Parameters.AddWithValue("Username", usernameTB.Text);
cmd.Parameters.AddWithValue("Password", passwordTB.Text);
cmd.Parameters.AddWithValue("Role", roleTB.Text);
cmd.Parameters.AddWithValue("Membership", membershipTB.Text);
cmd.Parameters.AddWithValue("DateOfReg", dorTB.Text);
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
find the Reference
However this way is not useful to me since I couple the DB connection to separate class since I have reuse it.
public class DBconnection{
public int insertQuery(String query) {
int affectedRowCount = 0;
SqlConnection conn = null;
try{
conn = new SqlConnection("Server=localhost;Database=master;UID=sa;PWD=sa;");
SqlCommand cmd = new SqlCommand( query, conn );
cmd.CommandType = CommandType.Text;
conn.Open( );
affectedRowCount = cmd.ExecuteNonQuery( );
conn.Close( );
} catch ( Exception e ){
String error = e.Message;
}
return affectedRowCount;
}
}
Therefore I only use bellow code part to call above class and Insert values to DB.
String SQLQuery1 = insert into Article values('" + Txtname.Text + "','" + TxtNo.Text + "','" + Txtdescription.Text + "' ,0)");
DBconnection dbConn = new DBconnection();
SqlDataReader Dr = dbConn.insertQuery(SQLQuery1);
Please help me to use Parameterize sqlString to Avoid me Sql Injection.
To use #name , # No and #description without use Textbox inputs.
It's perfectly reasonable to do this, but have your class call back (lambda/delegate) out to get the parameters. This is a static method in a class which is called by various overloaded instance methods:
private static int SqlExec(string ConnectionString, string StoredProcName, Action<SqlCommand> AddParameters, Action<SqlCommand> PostExec)
{
int ret;
using (var cn = new SqlConnection(ConnectionString))
using (var cmd = new SqlCommand(StoredProcName, cn))
{
cn.Open();
cmd.CommandType = CommandType.StoredProcedure;
if (AddParameters != null)
{
AddParameters(cmd);
}
ret = cmd.ExecuteNonQuery();
if (PostExec != null)
{
PostExec(cmd);
}
}
return ret;
}
Then, a usage example:
public void Save()
{
Data.Connect().Exec("Project_Update", Cm =>
{
Cm.Parameters.AddWithValue("#ProjectID", ID);
Cm.Parameters.AddWithValue("#PrimaryApplicantID", PrimaryApplicant.IdOrDBNull());
Cm.Parameters.AddWithValue("#SecondaryApplicantID", SecondaryApplicant.IdOrDBNull());
Cm.Parameters.AddWithValue("#ProjectName", ProjectName.ToDBValue());
});
}
It's also possible to do this with non-stored procedure calls.
In your case it would look like:
DBconnection.InsertQuery(
"INSERT INTO [UserData]
(Username, Password, Role, Membership, DateOfReg)
VALUES (#Username, #Password, #Role, #Membership, #DateOfReg)"
,cmd => {
cmd.Parameters.AddWithValue("Username", usernameTB.Text);
cmd.Parameters.AddWithValue("Password", passwordTB.Text);
cmd.Parameters.AddWithValue("Role", roleTB.Text);
cmd.Parameters.AddWithValue("Membership", membershipTB.Text);
cmd.Parameters.AddWithValue("DateOfReg", dorTB.Text);
}
);
Which puts all your database stuff together the way you want and lets the DBconnection keep its internals isolated.
How about instead of a generic InsertQuery() method you write specific InsertQuery methods?
For example:
public void AddNewUser(User u)
{
var query = "insert Users (name, password) values (#0, #1)";
SqlCommand cmd = new SqlCommand(query, conn);
try
{
cmd.Parameters.AddWithValue("#0", u.UserName);
cmd.Parameters.AddWithValue("#1", u.Password);
}
}
This has the advantage of ALL your SQL logic being in this other class, as opposed to the calling class needing to know how to construct the query etc.
It also makes your code more readable, because you see AddUser or UpdateUser or ChangePassword as method calls, and don't have to read SQL at that moment to try and guess what is going on in the program.
HOWEVER if you're going to do something like this, you should check out some MicroORMs, my personal favorite is PetaPoco (or the NuGet version)
PetaPoco and others like Massive and Dapper would let you do something like:
database.Insert(u);
Where u is a User object that maps to your DB's table. It uses ADO.NET and makes sure to use SQL Parameters.
I would suggest using LINQ to SQL, which automatically parametrizes everything.
Q. How is LINQ to SQL protected from SQL-injection attacks?
A. SQL injection has been a significant risk for traditional SQL queries formed by concatenating user input. LINQ to SQL avoids such injection by using SqlParameter in queries. User input is turned into parameter values. This approach prevents malicious commands from being used from customer input.
You can insert, update and delete from a SQL database in a straightforward manner using a DataContext (right-click on your project to add a new item and add the LINQ to SQL Classes template, then use the Server Explorer to add objects to it).
I haven't worked with this in a while, but I believe your code would then look somewhat like this:
UserData user = new UserData();
user.Username = ...;
user.Password = ...;
user.Role = ...;
user.Membership = ...;
user.DateOfReg = ...;
db.UserDatas.InsertOnSubmit(user);
db.SubmitChanges();
When you call SubmitChanges, LINQ to SQL automatically generates and executes the SQL commands that it must have to transmit your changes back to the database.
Edit1:
As an added note, to retrieve an existing item from a database, you could do this:
var user = (from i in db.UserDatas
where i.UserName == "devan"
select i).Single();
Oh, and as is my standard policy when answering questions about databases with login information, I must implore you, for the love of god and all that is holy, to salt and hash your users' passwords.

Categories