Is this bad coding?
I have a query
INSERT INTO sometable (field1,field2...fieldn) VALUES (?,?,.....?)
Then
cmd.Parameters.Add("TOFnr", OdbcType.Int, 10).Value = orderId;
cmd.Parameters.Add("LineNr", OdbcType.Int, 10).Value = maxLineNr;
cmd.Parameters.Add("Date", OdbcType.VarChar, 8).Value = rowHeader["Date"];
The code works, except there was an if-conditional around an Add, causing the data after that line to get into the wrong variable.
The placeholders ("TOFnr" etc.) is only used for the programmers reference, not used by the sql or c# itself, right?
Isn't it less error-prone to used named parameters in the query?
INSERT INTO sometable (field1,field2...fieldn) VALUES (#TOFnr,#LineNr,.....#fieldn)
It is c# connecting to borland paradox over odbc.
Isn't it less error-prone to used named parameters in the query?
Yes, it is. Unfortunately the ADO.NET ODBC driver doesn't allow named SQL parameters to be passed along in the SQL statement, so unfortunately for you, it is not possible using the ODBC driver.
I am not an expert on Paradox, but there might be a driver specifically for Paradox which does allow named parameters. You might have more luck there.
Related
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.
if i allow users to type in a textbox and then perform a search against my db, there is the potential for sql injection. i could use regex, thats my first thought. but i had a better idea. why not see if what they typed has any SQL keywords in it. Im using an SQL Server database, in an ASP.NET program with c#, i thought microsoft would have offered an easy solution to what i am talking about. the best i can find is in this article:
Is it a programmatic way to get SQL keywords (reserved words)
which is probably what ill end up doing, but my problem is i still have to type out the entire list of keywords, there is around a hundred. sure i could be done by now instead of searching and asking this question. but isnt there an easier way? right now im going to:
1 Create a Hashset
2 add all the keywords to the hashset (cmon)
3 validate user input against the hashset
would love to see step 2 be made much easier, any other suggestions about sql injections are also appreciated
If you are passing the search text into a stored procedure and doing something like
WHERE search LIKE #inputParam
SQL will not allow injection to incur in the above fragment.
However, if you are building a string variable and then using EXEC #sql or sp_execute #SQL, you are vulnerable to SQL injection.
In my opinion, you would be better off avoiding the problem of checking for SQL keywords altogether by using parameterized SQL. Here's an example in C# (assuming you're using MS SQL Server):
using (SqlCommand sqlcmd = new SqlCommand("SELECT * FROM [MyDB].[dbo].[MyTable] WHERE [SomeColumn] = #SomeValue", sqlconnection))
{
sqlcmd.Parameters.AddWithValue("#SomeValue", strUsersSearchString);
// use sqlcmd.ExecuteReader() here
// or whatever you normally would
}
Here's another example on MSDN. This one is using parameterized SQL to call a stored procedure: http://msdn.microsoft.com/en-us/library/ff648339.aspx#paght000002_step3
Use named parameters. Dapper-dot-net makes it really easy to do this:
IEnumerable<Row> results = connection.Query<Row>("SELECT column FROM table WHERE title LIKE #query", new { query = "SEARCHTERM" });
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
I want to use ODP.NET to run various queries on an oracle database and I'd like to use parameters in the query. Here's a trivial example snippet (omitting all the obvious setup bits of the OracleConnection):
string query = "SELECT FIRSTNAME FROM EMPLOYEES WHERE LASTNAME=:pNAME";
OracleCommand command = new OracleCommand(query);
command.Parameters.Add(":pNAME", OracleDBType.Varchar2).Value = "O'Brien";
My question is, is there anyway to see the query that gets generated from this? I know this is a simple example and the output is probably very obvious, but I'm trying to see how it actually handles things like escaping characters such as the ' in O'Brien. And of course in the future if my queries get more complicated and I'm getting sql errors, I thought I might be able to use the generated query to debug.
Any help or pointers is greatly appreciated!
SQL parameters are passed as parameters directly to SQL server, so there is no way to see it from your application. You can try checking it from Oracle side.
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.