I have a C# program that I want to dynamically create databases with. Although only privileged users will be using this application, I want to follow best practices security wise. How do I go about doing this? I don't think I can use a parameterized query in this case since I'm not wanting to pass in a string, I want to pass in an identifier.
Here's the insecure way I've got in there now as a placeholder:
using (MySqlConnection connection = new MySqlConnection(connectionString))
using (MySqlCommand command = connection.CreateCommand())
{
connection.Open();
command.CommandText = "DROP SCHEMA IF EXISTS " + schema;
command.ExecuteNonQuery();
command.CommandText = "CREATE SCHEMA " + schema;
command.ExecuteNonQuery();
}
Any ideas on this?
You can use the backtick delimiter to ensure the strings are correctly quoted and ensure that whatever is entered by the user is used as a literal identifier.
See: http://dev.mysql.com/doc/refman/5.0/en/identifiers.html and Using backticks around field names
That way the command that is passed to the server would look like: "DROP SCHEMA IF EXISTS foo" which will tolerate using reserved words and other incorrect string values as identifiers.
simply run a regular expression against schema to verify that it is a valid name? (contains no spaces, colons etc). I'm not sure if you can or can't use parameterised queries in this case, but if you do, it will fail creating a database called TRANCATE TABLE users; anyway :)
I don't know why do you want to create databases dynamically, but I think the correct way of doing this is not to generate databases dynamically.
The only exception I can think of is if you were creating your own database management system. If that's the case, maybe you could look at the source code of some open source MySQL database manager, like phpMyAdmin. (I don't know any for .Net.)
Related
I am working on a .net website which uses a DB2 database which uses Insert/Update and Select Queries. I researched about SQL Injection and I believe I've parametrized my query to avoid SQL Injection. Could you check if I've done it correctly and is there a better way or more sufficient way of doing it?
strInsert = "INSERT INTO DATABASE.Table(NUMBER,SIGNATURE,MESSAGE,CDATE,CTIME) VALUES (?,?,?,?,?)";
DB2Command cmdInsertQuery = new DB2Command(strInsert, db2Connection1);
cmdInsertQuery.Parameters.Add("NUMBER", i);
cmdInsertQuery.Parameters.Add("SIGNATURE", strSignature.Trim());
cmdInsertQuery.Parameters.Add("MESSAGE", strMessage.Trim());
cmdInsertQuery.Parameters.Add("CDATE", DateTime.Now.ToShortDateString());
cmdInsertQuery.Parameters.Add("CTIME", DateTime.Now.ToShortTimeString());
cmdInsertQuery.ExecuteNonQuery();
The query inserts the data correctly and works fine.
Yes, you have done it correctly. Good to know you are aware of SQL injection problems and trying ways to eradicate it.
add is deprecated use addwithvalue, it still almost does the same thing as add but my visual studio always cries about it
Example
string insertStatement =
"Insert Login VALUES(#username,#password,#publicKey,#privateKey,#salt)";
SqlCommand insertCommand = new SqlCommand(insertStatement, connection);
insertCommand.Parameters.AddWithValue("#username", username);
and is there a better way or more sufficient way of doing it?
one of options is to use
https://github.com/StackExchange/dapper-dot-net
This question already has answers here:
How does SQLParameter prevent SQL Injection?
(4 answers)
Closed 8 years ago.
I hope this is the right place to ask, how does parameters.addwithvalue work? I am thinking in a way to protect against SQL injection? I have been looking quite a lot on Stackoverflow, and a lot of people say "//Against sql injection". I have been using it blindly, but now that I have to hand in a paper about my assignment I need to explain why it is protection. I have been trying to find something on MSDN, found this one:
SQL injection But it uses the parameters.add. I then read that they replace .Add with .AddWithValue, is that true? Any official on this then?
So basically, anyone better in searching for some official paperwork that it protect against SQL injection? Or can tell me how it works?
I am not trying to make you do my work, I just can't find it my self.
I am using it like this:
using (SqlConnection conn = new SqlConnection(connectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
String queryString = "DELETE FROM dbo.SecurityAccess WHERE Username = ' #Username ";
cmd.CommandText = queryString;
cmd.Parameters.AddWithValue("#Username", Username);
cmd.ExecuteNonQuery();
}
From SQL Injection point of view using parameters is usually safe (subject to what you do with those parameters in the SQL...). Your example is safe. How one adds the parameters makes no difference from the SQL Ibjection point of view, but makes a lot of difference from ADO.Net and SQL performance point of view. AddWithValue is an anti-pattern because of performance problems related to parameter type and size. In your example the #UserName will be a parameter of type NVARCHAR, which will likely make the WHERE Username=#UserName predicate unsarg-able (will not use an index on Username). The execution result would be dreadful.
A potential solution to the datatype conversion is to use the explicit Add method instead of AddWithValue, which takes the datatype as second parameter. More details on this here.
For more details I urge you to read How Data Access Code Affects Database Performance.
In Short parameters allow for type safe and length checks on the data. Enabling a defense against SQL injection, they do not prohibit SQL injection completely you still need to check your inputs.
SO Answer on similar topic.
Good article explaining how parameters do not prevent SQL injection 100%
SQL Injection Example (Taken from MSDN:)
Consider what happens when a user types the following string in the SSN text box, which is expecting a Social Security number of the form nnn-nn-nnnn.
' ; DROP DATABASE pubs --
Using the input, the application executes the following dynamic SQL statement or stored procedure, which internally executes a similar SQL statement.
// Use dynamic SQL
SqlDataAdapter myCommand = new SqlDataAdapter(
"SELECT au_lname, au_fname FROM authors WHERE au_id = '" +
SSN.Text + "'", myConnection);
// Use stored procedures
SqlDataAdapter myCommand = new SqlDataAdapter(
"LoginStoredProcedure '" +
SSN.Text + "'", myConnection);
The developer's intention was that when the code runs, it inserts the user's input and generates a SQL the following statement.
SELECT au_lname, au_fname FROM authors WHERE au_id = '172-32-9999'
However, the code inserts the user's malicious input and generates the following query.
SELECT au_lname, au_fname FROM authors WHERE au_id = ''; DROP DATABASE pubs --'
Common ways to avoid Injection attacks.
•Constrain and sanitize input data. Check for known good data by validating for type, length, format, and range.
•Use type-safe SQL parameters for data access. You can use these parameters with stored procedures or dynamically constructed SQL command strings. Parameter collections such as SqlParameterCollection provide type checking and length validation. If you use a parameters collection, input is treated as a literal value, and SQL Server does not treat it as executable code. An additional benefit of using a parameters collection is that you can enforce type and length checks. Values outside of the range trigger an exception. This is a good example of defense in depth.
•Use an account that has restricted permissions in the database. Ideally, you should only grant execute permissions to selected stored procedures in the database and provide no direct table access.
•Avoid disclosing database error information. In the event of database errors, make sure you do not disclose detailed error messages to the user.
if you do not use Parameterised queries with above command then it looks like :
string queryString="DELETE FROM dbo.SecurityAccess WHERE Username = '"+txtUserName.Text+"'";
in the above command username would be assigned whatever user enters in TextBox( ex: txtUserName).
if user wants to inject some behaviour( adding delete/update or whatever he wants to do) he can enter following in TextBox (txtUserName)
=> "'';delete * from users"
then the above command with given username value looks like this:
string queryString="DELETE FROM dbo.SecurityAccess WHERE Username = '';delete * from users";
finally the above command would delete all the records from the users table.
Why table params aren't allowed in SQL Server? Is there any solution to this?
Example:
using (SqlCommand myCommand = new SqlCommand("SELECT * FROM #table WHERE USERNAME=#username AND PASSWORD=HASHBYTES('SHA1',
#password)", myConnection))
{
myCommand.Parameters.AddWithValue("#table", table);
myCommand.Parameters.AddWithValue("#username", user);
myCommand.Parameters.AddWithValue("#password", pass);
myConnection.Open();
SqlDataReader myReader = myCommand.ExecuteReader())
...................
}
Thanks.
You can't paramaterise that part of the SQL. The server needs to know the name of the table to be able to 'prepare' the query, which is done before the parameters are processed.
You might dynamically generate the query, but that may open you up to SQL injection attacks and run-time SQL syntax errors. Also, there is a saving to be had if an SQL statement can be cached by the server - you'll loose that if every query is dynamically generated.
Why? Because the benefit of flexibility is minor compared to the nightmare it would create in query optimization and validation.
As a sidenote, even if it was recognised you'd be getting a quoted string in the SQL, not just the table name. Dynamic SQL with heavy validation is the only real way of doing this.
If you have to pass a table of values...
XML parameter
CSV (String) parameter
Parse in SQL. See "Arrays and Lists in SQL Server 2005"
Otherwise, what are you trying to do?
Edit: I've got it now. As others mentioned, SQL does not work like that.
No, you cannot pass the table name as a param.
The best way would be to try using String.Format for the table name.
I would try to ilustrate my point of view about this with an example:
If you go to buy a car, you can "parametrize" some thinks: You can change the colour, may be some variations of the engine, you can put an MP3 or not, ... but you cant change the car model. If you change the car model, this is not a parameter, this is another car.
It is the same with sql query, the table is not a parameter is part of the sentence itself, same way that the command is (select, update) .. so you can't do #command from #table. If you change the table, this is another sentence, like the car.
(this is not a technical "because" answer for you question, but a conceptual point of view for better understanding of the techical part that others are posting)
My two cents.
I'm using Microsoft Visual C# 2008 Express Edition with SqlLite. I'm successfully able to open my database and with C# code, add entries to my tables.
When it comes to retriving data, I'm having some issues and have been searching and searching the internet for basic tutorial information on how to do these basic things...
Here's my code... (after I've opened up a connection to the database which is called 'conn' here):
SQLiteCommand cmd = new SQLiteCommand(conn);
cmd.CommandText = "select myField1,myField2 from myTable where myField3 = '" + tempstring + "';";
cmd.CommandType = CommandType.Text;
SQLiteDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
string tmp = reader.GetString(0);
System.Console.WriteLine(" my output = " + tmp);
}
When I execute this... I get no errors and because I get no output on that last line, it looks like the while loop is not executing at all.
I'm a beginner to this stuff... what am I missing and is there a good web resource where I can learn these basic things? I'm pretty comfortable in SQL on it's own... just not integrated in C# like this...
First, remove the hurtful trailing semicolon from the line while (reader.Read());...!
This looks correct to me. Does the property reader.HasRows return true for your query?
A couple of side issues to be aware of are:
Be sure to dispose of your SQL resources by wrapping your objects in using { } blocks.
Consider using parameterized queries instead of injecting the query parameter directly in the SELECT statement.
Answering your question on how to write parameterized queries:
cmd.CommandText = "select myField1,myField2 from myTable where myField3 = #tempString;";
SQLiteParameter param = new SQLiteParameter("#tempString");
cmd.Parameters.Add(param);
// you can modify that value without touching the sql statement (which means you could cache the above command)
param.Value = tempstring;
SQLiteDataReader reader = cmd.ExecuteReader();
[...]
Parameters in SQLite can have several forms which you can find here.
See here for more info on parameterized queries.
Good one, Alex.
In addition to that and since you are beginning with sqlite (you may want to delete second L from the tag), remember that sqlite does not really guaranty data type safety on the database level.
Not to divert you from your Sqlite question, but if you are having comfort issues with Sqlite queries embedded in C#, you could try NHibernate coupled with Fluent NHibernate. These technologies provide an excellent data access mechanism into databases, including Sqlite.
NHibernate requests into Sqlite are very fast, and you won't have to worry about some of the Sqlite idiosyncrasies. If you build out your data-access layer properly with NHibernate, you should be able to up-scale to a more robust database very quickly.
I know there have been numerous questions here about inline sql vs stored procedures...
I don't want to start another one like that! This one is about inline (or dynamic) sql.
I also know this point has become more or less moot with Linq to SQL and its successor Entity Framework.
But... suppose you have chosen (or are required by your superiors) to work with plain old ADO.NET and inline (or dynamic) sql. What are then the best practices for this and for formatting the sql?
What I do now is the following:
I like to create my SQL statements in a stored procedure first. This gives me syntax coloring in SQL Server Management Studio and the ability to test the query easily without having to execute it in code through the application I'm developing.
So as long as I'm implementing/debugging, my code looks like this:
using (SqlConnection conn = new SqlConnection("myDbConnectionString"))
{
conn.Open();
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "myStoredProcName";
// add parameters here
using (SqlDataReader rd = cmd.ExecuteReader())
{
// read data and fill object graph
}
}
}
Once the debugging and testing phase is done, I change the code above like this:
using (SqlConnection conn = new SqlConnection("myDbConnectionString"))
{
conn.Open();
using (SqlCommand cmd = conn.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = GetQuery();
// add parameters here
using (SqlDataReader rd = cmd.ExecuteReader())
{
// read data and fill object graph
}
}
}
And I add an extra private method e.g. GetQuery() in which I copy/paste the whole block of the stored procedure like this:
private string GetQuery()
{
return #"
SET NOCOUNT ON;
SELECT col1, col2 from tableX where id = #id
-- more sql here
";
}
Working like this has the benefit that I can revert the code easily to call the stored procedure again if I have to debug/update the sql code later, and once it's done I can easily put the sql code back with copy/paste, without having to put quotes around every line and stuff like that.
Is it good practice to include newlines in the query?
Are there other things or tricks that I haven't thought of which can make this approach better?
How do you guys do things like this?
Or am I the only one who still uses (has to use) inline sql?
Inline (with or without the literal #"..." syntax) is fine for short queries... but for anything longer, consider having the tsql as a file in the project; either as embedded resources / resx, or as flat files. Of course, by that stage, you should probably make it a stored procedure anyway ;-p
But having it as a separate file forces the same separation that will make it a breeze to turn into a stored procedure later (probably just adding CREATE PROC etc).
One issue with inline - it makes it so tempting for somebody to concatenate user input... which is obviously bad (you've correctly used parameters in the example).
I've used .NET resource files in the past. These were handy for keeping a library of all queries used in a particular code library, particularly when the same query might be used in multiple places (yes, I realize this also indicates some poor design, but sometimes you need to work within the box given to you).
Beyond non-trival single-line SQL statements, I always take advantage to multi-line and make it a const
const string SelectMyTable = #"
SELECT column_one
, column_two
, column_three
FROM my_table
";
This all allows me to cut and paste to SQL manager for testing.