Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Properly securing SQL statement with parameters

Tags:

c#

sql

sql-server

I have two SQL statements in my C# code to retrieve some values. I know they are open to SQL injection since I'm not using parameters, but I'm not sure if I'm implementing them correctly.

(Note: each of these are in loops that are looping through rows of a data table) First example:

string sql2 = "select max(day) as day from users u join days d on d.User_ID = u.id where u.ActiveUser = 1 and u.id = " + Users["ID"].ToString();
command.CommandText = sql2;               
string dt = command.ExecuteScalar().ToString(); 

In the above statement, it's retrieving a datetime and assigning it to string dt. Anything with id or ID in it is a bigint.

string sql = "SELECT MAX(Day) FROM Days WHERE Project_ID IN (SELECT ID FROM Projects WHERE Parent_ID = -1 AND ID = " + row["ID"] +  ") HAVING MAX(Day) < DATEADD(dd, -730, getdate())";
command.CommandText = sql;                                  
object val = command.ExecuteScalar();

The above statement is the same as the first statement, as in it's retrieving a datetime value. Anything with id or ID is a bigint.

Here's what I came up with for the first one, am I missing anything or doing something wrong?

string sql2 = "select max(day) as day from users u join days d on d.User_ID = u.id where u.ActiveUser = 1 and u.id = @userID";
using (conn)
{
     using (SqlCommand cmd = new SqlCommand(sql2, conn))
     {
          command.Parameters.AddWithValue("@userID", drUsers["ID"]);
          conn.Open();
          dt = (DateTime)command.ExecuteScalar();
     }
}

Note: I asked a question last week on DateTime conversions and there was an issue that couldn't be resolved, so I might have to just use a string version of the datetime that is returned. Will that affect anything?

like image 207
pfinferno Avatar asked Dec 15 '15 13:12

pfinferno


People also ask

Are parameterized queries safe from SQL injection?

Use prepared statements and parameterized queries. These are SQL statements that are sent to and parsed by the database server separately from any parameters. This way it is impossible for an attacker to inject malicious SQL.

Why are parameterized SQL queries important for secure applications?

The only sure way to prevent SQL Injection attacks is input validation and parametrized queries including prepared statements. The application code should never use the input directly. The developer must sanitize all input, not only web form inputs such as login forms.

What's a recommended way of dealing with SQL injection attacks?

Developers can prevent SQL Injection vulnerabilities in web applications by utilizing parameterized database queries with bound, typed parameters and careful use of parameterized stored procedures in the database. This can be accomplished in a variety of programming languages including Java, . NET, PHP, and more.


1 Answers

It would be like:

string sql2 = @"select max(day) as day from users u 
join days d on d.User_ID = u.id 
where u.ActiveUser = 1 and u.id = @id";

string sql = @"SELECT MAX(Day) FROM Days 
WHERE Project_ID IN 
(SELECT ID FROM Projects WHERE Parent_ID = -1 AND ID = @id)
HAVING MAX(Day) < DATEADD(dd, -730, getdate())";

DateTime dt;
using (conn)
{
  using (SqlCommand cmd = new SqlCommand(sql2, conn))
  {
    cmd.Parameters.AddWithValue("@id", (Int64)Users["ID"]);
    conn.Open();
    dt = (DateTime)cmd.ExecuteScalar();
  }
}

using (conn)
{
  using (SqlCommand cmd = new SqlCommand(sql, conn))
  {
    cmd.Parameters.AddWithValue("@id", (Int64)row["ID"]);
    conn.Open();
    dt = (DateTime)cmd.ExecuteScalar();
  }
}

However, for performance reasons, I wouldn't do this once per row in the DataTable. You can simply get all the max(day) values grouped by ID once to client side. ie:

string sql = @"select u.Id, max(day) as day 
  from users u 
  join days d on d.User_ID = u.id 
  where u.ActiveUser = 1
  group by u.id";

EDIT: I saw your edit later, and the added question about datetime. Do not convert a datetime value to a string. It is where the errors begin. If you "HAVE TO" then use only ODBC canonical format which is not affected from SQL server settings - yyyyMMdd. Other types of datetime strings would only work by chance if they ever do.

like image 155
Cetin Basoz Avatar answered Oct 13 '22 02:10

Cetin Basoz