Parameterized field name - sql

I was thinking if this will work:
Dim query As String = "UPDATE tblPiglets SET #to=#todate, CurrentLocation=#to" & _
" WHERE Week=#week AND SowOrder=#so AND PigletNumber=#pig"
But I caught Cannot update #to field lol
The #to is a variable in which I thought would work the same its value though its worth a try. Its value is dependent on a user input, so, is there any other way to do that?
Or this? (not sure if this will work though):
Dim to As String = "foo"
Dim query As String = "UPDATE tblPiglets SET " & to & "=#todate, CurrentLocation=#to" & _
" WHERE Week=#week AND SowOrder=#so AND PigletNumber=#pig"

It is always preferable to use parameters to insert user input into SQL code but parameters can only be used for values, not identifiers. Think of SQL parameters the same as parameters in a VB method. You can't use a method parameter to specify a property or method to use and you can't use a SQL parameter to specify a column or table.
You have no choice but to use string concatenation but doing so opens you up to SQL injection, so make absolutely sure that the user cannot insert arbitrary SQL code. If it's a column name then they should have to select it from a list that you have retrieved from the database itself, so that you are guaranteed that it's a valid column.

I have used option 2 to make it work.
Dim to As String = "foo"
Dim query As String = "UPDATE tblPiglets SET " & to & "=#todate, CurrentLocation=#to" & _
" WHERE Week=#week AND SowOrder=#so AND PigletNumber=#pig"
But it would be nicer if I can get the same result if I will be using the first option. thanks

Related

hash password different between query text and query parameter

i want to ask is it different to hashbytes by query and parameter ?
my code is
.CommandText = "update table.pass " _
& "set password = convert(varchar(12),HASHBYTES('MD5','" & TextEdit3.Text.ToUpper.ToString & "'),2) where userid='" + USER_ID + "'"
my second code is
.CommandText = "update table.pass " _
& " set password = convert(varchar(12),HASHBYTES('MD5',#pass),2) where userid=#userid"
.Parameters.AddWithValue("#pass", TextEdit3.Text.ToUpper.ToString)
.Parameters.AddWithValue("#userid", USER_ID)
for now iam using the first code, and i know it's wrong due to sql injection. so i want to use the second code. but the result was different from the first code.
what i want is, how do i use parameter but the result is same with the first code, because my predecessor use the first one
I believe that AddWithValue assumes nvarchar for String data. It is generally recommended to use Add and specify the data type yourself when there is any doubt about which data type will be used. If you do that and specify VarChar then you should get the same result.
EDIT: Either that or put an 'N' prefix in the first code, i.e.
"set password = convert(varchar(12),HASHBYTES('MD5',N'"

Vb 2015 query with parameters not working

I already used parametrized queries with no problem, but today I'm stuck on an error that I cannot debug.
This is my working query
cmd.CommandText = "select idcliente, ragsociale from Clienti where idcliente =" & strName & " or codiceamministrazione='" & strName & "' or piva='" & strName & "' or codfisc='" & strName & "'"
The same, but with parameter, not working
cmd.CommandText = "select idcliente, ragsociale from Clienti where idcliente = #Cliente or codiceamministrazione=#Cliente or piva=#Cliente or codfisc=#Cliente"
cmd.Parameters.AddWithValue("#Cliente", strName)
I use this in an autocomplete procedure that shows the name of a client based on internal id or on commercial license number (and other similar codes). On the db a client record can have all the code fields compiled or just 1.
With the non-parametrized query the autocomplete suggestion pop-up,with the parametrized one nothing shows. No errors either.
EDIT:
using this
cmd.Parameters.Add("#Cliente", SqlDbType.VarChar)
cmd.Parameters("#Cliente").Value = strName
now another query (omitted before for semplicity) in the same function works, but, strange enough, the one for what I did this question don't.
Working:
cmd.CommandText = "select idcliente, ragsociale from Clienti where ragsociale like '%'+#Cliente+'%' or codiceamministrazione=#Cliente"
Still not Working:
cmd.CommandText = "select idcliente, ragsociale from Clienti where idcliente = #Cliente or piva=#Cliente or codfisc=#Cliente"
In your original query, when testing against idcliente, you treat strName as a number (no quotes round it), but for all the other fields you treat it like a string. So you're implying it could potentially contain a number or a string. This is problematic, if you type a number, and the parameterised version of the query now treats it like a string in all cases, then it won't match the numeric value of idcliente in the DB and therefore you may get no results.
To clarify: if your input is a number, but your query thinks it's a string (because of the data type in the param), it will not match against any numeric field in the database. 12345 != "12345".
You need to define separate parameters for these scenarios. You can pass the same value into them, but in one case set the parameter's datatype to varchar and in the other case to int (you might need to check if the value can be parsed as a number before you do this, otherwise it will likely crash. In that case just set it null or 0 or something that won't make an accidental match).

Inserting Single/double type to DB using VBA in access

I need some help with an issue that is doing my head in.
I need to update a database in access and its been working fine operating with Long and Integers.
Look at this code.
sql = "UPDATE DBNAME SET Long_Field = " & Long_Variable & " WHERE ID = " & id
DoCmd.SetWarnings (False)
DoCmd.RunSQL sql
This code runs flawlessly, it takes a long variable and puts it into the correct field which is set as Long.
However, if I want to populate a single/double field (ive tried both)
sql = "UPDATE DBNAME SET Double_Field = " & double_Variable & " WHERE ID= " & id
DoCmd.SetWarnings (False)
DoCmd.RunSQL sql
I keep getting Run-Time error 3144: Syntax error in update statement.
I can literally just switch out the field name and the variable name and the code runs flawlessly, but as soon as i try to send a double value, for example (5,8), to a field in the table that is set to double, it gives me this error.
Anyone?
I assume that you want a dot as decimal separator in your string.
The conversion from double to string is done using the separator from the system locale settings so in your case a comma.
This means that
double_variable = 5.8
sql = "... " & double_variable & " ..."
will produce ... 5,8 ... in the sql variable.
The easiest way to fix that is to use
"..." & Replace(CStr(double_variable), ",", ".") & "..."
This will replace all , with .. I put the CStr there to make sure it gets converted to a string first. It will also work if the system locale changes since nothing will happen if there is no ,. The only caveat is that if for some reason the conversion inserts 1000s separators it will fail but that would only be relevant in other circumstances as I don't think CStr will ever do that.
The current answer is not the easiest, neither the simplest.
The universal method is to use Str as it always returns a dot as the decimal separator:
sql = "UPDATE DBNAME SET Double_Field = " & Str(double_Variable) & " WHERE ID = " & id & ""

MS Access parameterized queries VB

dbs.Execute " INSERT INTO Log " _
& "(UserName, DateAccessed) VALUES " _
& "(#GetLogonName, #Today);"
GetLogonName and Today are variables but I get error "error- too few parameters, expected two". If I run the function using actual values like &"('abce', '2/2/2012') it works.
What am I doing wrong?
Thanks
Database.Execute doesn't accept query parameters, only the execution options defined in RecordsetOptionEnum.
To run a parameterized query you need to create a QueryDef object:
Dim query As QueryDef
Set query = dbs.CreateQueryDef("", "INSERT INTO LOG (UserName,DateAccessed)" & _
" VALUES(#user,#time)")
query.Parameters("#user").Value = "Moo"
query.Parameters("#time").Value = Now
query.Execute
The empty string means this is a temporary QueryDef. If you enter any other name, or omit the name entirely, a new Query object will be created in the database.
If you use the same query frequently, it's a good idea to create a Query and call it by name:
Set query = dbs.QueryDefs("myQueryName")
...
QueryDef.Execute accepts the same execution parameters as Database.Execute

Can my users inject my dynamic sql?

I'm a desktop developer writing for internal users, so I'm not worried about malicious hackers, but I would like to know if there's anything they could enter when updating a value that would execute sql on the server.
The business defines their content schema and I have a CRUD application for them that doesn't have to be changed when their schema changes because the validation details are table-driven and the updates are with dynamic SQL. I have to support single quotes in their data entry, so when they enter them, I double them before the SQL is executed on the server. From what I've read, however, this shouldn't be enough to stop an injection.
So my question is, what text could they enter in a free-form text field that could change something on the server instead of being stored as a literal value?
Basically, I'm building an SQL statement at runtime that follows the pattern:
update table set field = value where pkField = pkVal
with this VB.NET code:
Friend Function updateVal(ByVal newVal As String) As Integer
Dim params As Collection
Dim SQL As String
Dim ret As Integer
SQL = _updateSQL(newVal)
params = New Collection
params.Add(SQLClientAccess.instance.sqlParam("#SQL", DbType.String, 0, SQL))
Try
ret = SQLClientAccess.instance.execSP("usp_execSQL", params)
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
Return ret
End Function
Private Function _updateSQL(ByVal newVal As String) As String
Dim SQL As String
Dim useDelimiter As Boolean = (_formatType = DisplaySet.formatTypes.text)
Dim position As Integer = InStr(newVal, "'")
Do Until position = 0
newVal = Left(newVal, position) + Mid(newVal, position) ' double embedded single quotes '
position = InStr(position + 2, newVal, "'")
Loop
If _formatType = DisplaySet.formatTypes.memo Then
SQL = "declare #ptrval binary(16)"
SQL = SQL & " select #ptrval = textptr(" & _fieldName & ")"
SQL = SQL & " from " & _updateTableName & _PKWhereClauses
SQL = SQL & " updatetext " & _updateTableName & "." & _fieldName & " #ptrval 0 null '" & newVal & "'"
Else
SQL = "Update " & _updateTableName & " set " & _fieldName & " = "
If useDelimiter Then
SQL = SQL & "'"
End If
SQL = SQL & newVal
If useDelimiter Then
SQL = SQL & "'"
End If
SQL = SQL & _PKWhereClauses
End If
Return SQL
End Function
when I update a text field to the value
Redmond'; drop table OrdersTable--
it generates:
Update caseFile set notes = 'Redmond''; drop table OrdersTable--' where guardianshipID = '001168-3'
and updates the value to the literal value they entered.
What else could they enter that would inject SQL?
Again, I'm not worried that someone wants to hack the server at their job, but would like to know how if they could accidentally paste text from somewhere else and break something.
Thanks.
Regardless of how you cleanse the user input increasing the attack surface is the real problem with what you're doing. If you look back at the history of SQL Injection you'll notice that new and even more creative ways to wreak havoc via them have emerged over time. While you may have avoided the known it's always what's lurking just around the corner that makes this type of code difficult to productionize. You'd be better to simply use a different approach.
You can also evaluate an alternative solution. Dynamic generation of SQL with parameters. Something like this:
// snippet just for get the idea
var parameters = new Dictionary<string, object>();
GetParametersFromUI(parameters);
if (parameters.ContainsKey("#id")) {
whereBuilder.Append(" AND id = #id");
cmd.Parameters.AddWithValue("#id", parameters["#id"]);
}
...
Assuming you escape string literals (which from what you said you are doing), you should be safe. The only other thing I can think of is if you use a unicode-based character set to communicate with the database, make sure the strings you send are valid in that encoding.
As ugly as your doubling up code is (:p - Try String.Replace instead.) I'm pretty sure that will do the job.
The only safe assumption is that if you're not using parameterized queries (and you're not, exclusively, here, because you're concatenating the input string into your sql), then you're not safe.
You never never ever never want to build a SQL statement using user input that will be then directly executed. This leads to SQL injection attacks, as you've found. It would be trivial for someone to drop a table in your database, as you've described.
You want to use parameterized queries, where you build an SQL string using placeholders for the values, then pass the values in for those parameters.
Using VB you'd do something like:
'Define our sql query'
Dim sSQL As String = "SELECT FirstName, LastName, Title " & _
"FROM Employees " & _
"WHERE ((EmployeeID > ? AND HireDate > ?) AND Country = ?)"
'Populate Command Object'
Dim oCmd As New OledbCommand(sSQL, oCnn)
'Add up the parameter, associated it with its value'
oCmd.Parameters.Add("EmployeeID", sEmpId)
oCmd.Parameters.Add("HireDate", sHireDate)
oCmd.Parameters.Add("Country", sCountry)
(example taken from here) (also not I'm not a VB programmer so this might not be proper syntax, but it gets the point across)