Preventing SQL from injection attacks - vb.net

I have a program that contains SQL queries, and it was pointed out to me yesterday that it was wide open to SQL injection attacks. After doing some research, I could see that to fix this, I needed to use parameters instead.
I have the following code... How do paramterise this?
Public Shared Function SaveNewPerson(ByVal firstName As String, lastName As String, ByVal age As Integer, ByVal postcode As String, m_cn As OleDbConnection)
Dim tr As OleDbTransaction = Nothing
Try
tr = m_cn.BeginTransaction()
Dim Dc As New OleDbCommand
Dc.Connection = m_cn
Dc.CommandText = "INSERT INTO tblPerson([firstName], [lastName], [age], [postcode]) VALUES('" & firstName & "', '" & lastName & "', '" & age & "', '" & postcode & "')"
Dc.Transaction = tr
Dc.ExecuteNonQuery()
Dim personID As Integer
Dc.CommandText = "SELECT SCOPE_IDENTITY() AS personID"
Dc.CommandType = CommandType.Text
personID = CType(Dc.ExecuteScalar(), Integer)
tr.Commit()
Catch ex As Exception
tr.Rollback()
Throw
End Try
End Function

I would make a stored procedure first to insert into the sql server and then use
dc.commandText = "Your stored procedure name"
dc.commandType = CommandType.StoredProcedure
Dim myParam as oledb.OleDbParameter = dc.parameters.add("#personID", oledbtype.int)
myParam.Direction = ParameterDirection.ReturnValue
dc.Parameters.Add("#firstName", OleDbType.VarChar).Value = [firstname]
....
....
Dim returnId as Integer = Cint(dc.Parameters("#personID").Value)

Dc.CommandText = "INSERT INTO tblPerson([firstName], [lastName], [age], [postcode]) VALUES('" & firstName & "', '" & lastName & "', '" & age & "', '" & postcode & "')"
Change this to
Dc.CommandText = "INSERT INTO tblPerson([firstName], [lastName], [age], [postcode]) VALUES(?, ?, ?, ?)"
Dc.Parameters.Add("#first", OleDbType.VarChar, firstName)
Dc.Parameters.Add("#last", OleDbType.VarChar, lastName)
Dc.Parameters.Add("#age", OleDbType.Integer, age)
Dc.Parameters.Add("#postcode", OleDbType.VarChar, postcode )
(Check the right OldDbType value is passed.)
NB. the order in the parameters collection determines which parameter matches which ? placeholder. The names given to the parameters are (it seems) ignored.

Related

Syntax error in INSERT INTO statement. VB.NET AND MS-ACCESS

I think I have check thoroughly, I indicated the 7 field names as well as the the seven boxes where the data will be stored and send to the database...
I'm not sure where specifically the syntax error, thank you!
Private Sub AddBtn_Click(sender As Object, e As EventArgs) Handles AddBtn.Click
If UsernameTxt.Text = Nothing Or PasswordTxt.Text = Nothing Or FullNameTxt.Text = Nothing Or EmailTxt.Text = Nothing Or AddressTxt.Text = Nothing Or ContactNumberTxt.Text = Nothing Or UserTypeTxt.Text = Nothing Then
MsgBox("Please Input Credentials", MsgBoxStyle.OkOnly)
Else
Dim sql As String
Dim cmd As New OleDbCommand
Dim i As Integer
Try
con.Open()
sql = "INSERT INTO userTable (userName,passWord,fullName,userType,e_mail,home_address,contact_number) values ('" & UsernameTxt.Text & "', '" & PasswordTxt.Text & "', '" & FullNameTxt.Text & "', '" & UserTypeTxt.Text & "', '" & EmailTxt.Text & "', '" & AddressTxt.Text & "', '" & ContactNumberTxt.Text & "');"
cmd.Connection = con
cmd.CommandText = sql
i = cmd.ExecuteNonQuery
If i > 0 Then
MsgBox("Record Added SuccessFully")
Else
MsgBox("Error Adding Record")
End If
Catch ex As Exception
MsgBox(ex.Message)
Finally
con.Close()
End Try
End If
End Sub
All the advice about parameters stands but, even if there are other issues, one that has not been addressed is that "Password" is a reserved word in Jet/ACE SQL. That means that you need to escape that column name no matter what else you do:
sql = "INSERT INTO userTable (userName,[passWord],fullName,..."
Passwords should not be stored in the clear anyway so, if you are doing the right thing and hashing passwords, you can name your column "PasswordHash" and there's no issue.
Congratulations, you've discovered one of the reasons why it's important to use parameters in your SQL command statements -- they allow you to write a statement and fill in arbitrary data values without worrying about how the SQL syntax will be affected:
For Each textbox As TextBox In {UsernameTxt, PasswordTxt, FullNameTxt, UserTypeTxt, EmailTxt, AddressTxt, ContactNumberTxt}
Dim prm = cmd.Parameters.Add(textbox.Name, OleDbType.VarWChar)
prm.Value = textbox.Text
Next
con.Open()
sql = "INSERT INTO userTable (userName, passWord, fullName, userType, e_mail, home_address, contact_number) values (?, ?, ?, ?, ?, ?, ?)"
cmd.Connection = con
cmd.CommandText = sql
For an introduction on how to use parameters in ADO.NET, see here.

SQL transaction statement in vb.net

I'm making a project that is linked to Microsoft SQLServer, used to enter, remove, edit data about customers and orders. The full system works, however I've been advised to use transactions rather than regular SQL statements to add/remove/edit data etc.
The trouble is, I've not used these before and from my research over the last few hours, I can't work out how to even begin them.
Can anybody advise me how to turn the following code into a transaction?
Public Shared Function SaveNewPerson(ByVal firstName As String, lastName As String, ByVal age As Integer, ByVal postcode As String, m_cn As OleDbConnection)
Dim Dc As New OleDbCommand
Dc.Connection = m_cn
m_cn.Open()
Dc.CommandText = "INSERT INTO tblPerson([firstName], [lastName], [age], [postcode]) VALUES('" & firstName & "', '" & lastName & "', '" & age & "', '" & postcode & "')"
Dc.ExecuteNonQuery()
Dim personID As Integer
Dc.CommandText = "SELECT ##IDENTITY"
Dc.CommandType = CommandType.Text
personID = CType(Dc.ExecuteScalar(), Integer)
m_cn.Close()
End Function
I've just been learning TSQL, see if this sort of code will work for you (note that you need to Dim tr (with a different variable name, if you like) and use it in multiple places, but unlike in some languages you don't need to set up objects for the different methods.
Public Shared Function SaveNewIncident(ByVal clientName As String, dateStart As Date, dateEnd As Date, ByVal incidentProblem As String, ByVal timeStart As String, ByVal timeEnd As String,
ByVal incidentSolved As Boolean, ByVal incidentSolution As String, _con As OleDbConnection)
Dim tr As OleDbTransaction = Nothing
Try
Dim Dc As New OleDbCommand
Dc.Connection = _con
tr = _con.BeginTransaction()
Dc.CommandType = CommandType.Text
Dc.CommandText = "INSERT INTO dbo.tblIncidents VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)"
Dc.Transaction = tr
Dc.Parameters.Add("#clientName", OleDbType.VarChar).Value = clientName
Dc.Parameters.Add("#dateStart", OleDbType.Date).Value = dateStart
Dc.Parameters.Add("#dateEnd", OleDbType.Date).Value = dateEnd
Dc.Parameters.Add("#incidentProblem", OleDbType.LongVarChar).Value = incidentProblem
Dc.Parameters.Add("#timeStart", OleDbType.VarChar).Value = timeStart
Dc.Parameters.Add("#timeEnd", OleDbType.VarChar).Value = timeEnd
Dc.Parameters.Add("#incidentSolved", OleDbType.Boolean).Value = incidentSolved
Dc.Parameters.Add("#incidentSolution", OleDbType.LongVarChar).Value = incidentSolution
Dim personID As Integer
Dc.CommandText = "SELECT SCOPE_IDENTITY() AS personID"
Dc.CommandType = CommandType.Text
personID = CType(Dc.ExecuteScalar(), Integer)
tr.Commit()
Catch ex As Exception
tr.Rollback()
Throw
End Try
End Function

Combining two Columns

I have an SQL table with 4 columns. The fourth column is FullName. I want this column to autofill itself from the results of 2nd and 3rd Column. ie.Firstname and Middlename.
I have tried this code
cn.Open()
Dim query As String
query = "Insert into Details(Adm,FirstName,MiddleName,FullName ) VALUES ('" & TextBox1.Text & "' , '" & TextBox2.Text & "', '" & TextBox3.Text & " ', CONCATE(Textbox2.text, ',', Textbox3.Text))"
cmd = New SqlCommand(query, cn)
reader = cmd.ExecuteReader
MessageBox.Show("Data Saved")
The section CONCATINATE will be like the following:
"CONCATE('" & Textbox2.text &"',',','" & Textbox3.Text & "'))"
But i wont tell you to use like this, since it may a worst suggestion. I prefer you to use parameters as well to avoid injection and specifying the types.
Example:
Dim query = "Insert into Details(Adm,FirstName,MiddleName,FullName ) VALUES (" & _
"#adm,#fName,#mName,CONCATE(#fNameC,',',#mNameC))"
Dim cmd As New SqlCommand(query, cn)
cmd.Parameters.Add("#adm", SqlDbType.VarChar).Value = TextBox1.Text
cmd.Parameters.Add("#fName", SqlDbType.VarChar).Value = TextBox2.Text
cmd.Parameters.Add("#mName", SqlDbType.VarChar).Value = TextBox3.Text
cmd.Parameters.Add("#fNameC", SqlDbType.VarChar).Value = TextBox2.Text
cmd.Parameters.Add("#mNameC", SqlDbType.VarChar).Value = TextBox3.Text
'Execute the query here
Before query first store two textbox value in one variable
cn.Open()
Dim query As String
Dim fullname As String
fullname = TextBox1.text + "" + TextBox2.text
query = "Insert into Details(Adm,FirstName,MiddleName,FullName ) VALUES ('" & TextBox1.Text & "' , '" & TextBox2.Text & "', '" & TextBox3.Text & " ', '" & fullname & '")"
cmd = New SqlCommand(query, cn)
reader = cmd.ExecuteReader
MessageBox.Show("Data Saved")
You can concatenate with String.Concat, and I advice you to use the Parameter to avoid sql injections, like this :
cn.Open()
Dim query As String
query = "Insert into Details(Adm,FirstName,MiddleName,FullName ) VALUES (#Adm,#FirstName,#MiddleName,#FullName)"
cmd = New SqlCommand(query, cn)
cmd.Parameters.Add(New SqlParameter("#Adm", TextBox1.Text))
cmd.Parameters.Add(New SqlParameter("#FirstName", TextBox2.Text))
cmd.Parameters.Add(New SqlParameter("#MiddleName", TextBox3.Text))
cmd.Parameters.Add(New SqlParameter("#FullName", String.Concat(TextBox2.Text, ",", TextBox3.Text)))
reader = cmd.ExecuteReader
MessageBox.Show("Data Saved")
Save the Firstname and Middlename values into variables and concat() them together before sending to the query.
cn.Open()
Dim query As String
Dim firstname As String
Dim middlename As String
Dim fullname As String
query = "Insert into Details(Adm,FirstName,MiddleName,FullName) VALUES (#Adm,#FirstName,#MiddleName,#FullName)"
firstname = TextBox2.Text
middlename = TextBox3.Text
fullname = String.Concat(firstname, ",", middlename)
cmd = New SqlCommand(query, cn)
cmd.Parameters.Add(New SqlParameter("#Adm", TextBox1.Text))
cmd.Parameters.Add(New SqlParameter("#FirstName", firstname))
cmd.Parameters.Add(New SqlParameter("#MiddleName",middlename))
cmd.Parameters.Add(New SqlParameter("#FullName", fullname))
reader = cmd.ExecuteReader
MessageBox.Show("Data Saved")
Note that the query builder has been reformatted to remove vulnerability to SQL injection.
Use following line instead of your.
query = "Insert into Details(Adm,FirstName,MiddleName,FullName ) VALUES ('" & TextBox1.Text & "' , '" & TextBox2.Text & "', '" & TextBox3.Text & " ', '" & Textbox2.Text & " " & Textbox3.Text & "')"

data is not inserted to database

i tried to insert the data into database with this code
Public Sub AddUser()
Dim con As dbConn = New dbConn()
Dim SqlSelect As String
SqlSelect = "SELECT * FROM login Where user_id='" & WorkerID_.Text & "'"
Dim cmd As New OleDbCommand(SqlSelect, con.oleconnection)
Dim reader As OleDbDataReader
Dim da As New OleDbDataAdapter
con.open()
reader = cmd.ExecuteReader()
reader.Read()
If reader.HasRows() Then
reader.Close()
con.close()
FailureText.Text = "User ID already exists!"
Else
reader.Close()
con.close()
Dim InsertSQL As String
InsertSQL = "INSERT INTO login (user_id, user_role, user_password, user_status) VALUES "
InsertSQL &= "('" & WorkerID_.Text & "', "
InsertSQL &= "'Worker', "
InsertSQL &= "'12345', 1)"
Dim SqlUpdate As String
SqlUpdate = "INSERT INTO Worker (ID, WorkerID, WorkerName, DoB, Address, Phone, Email, CompanyName, PassportNum, PassportExp, VisaExp, VisaStatus, user_id) VALUES (default,"
SqlUpdate &= "'" & WorkerID_.Text & "', "
SqlUpdate &= "'" & WorkerName.Text & "', "
SqlUpdate &= "'" & DoB.Text & "', "
SqlUpdate &= "'" & Address.Text & "', "
SqlUpdate &= "'" & Phone.Text & "', "
SqlUpdate &= "'" & Email.Text & "', "
SqlUpdate &= "'" & Company.SelectedValue & "', "
SqlUpdate &= "'" & PassNum.Text & "', "
SqlUpdate &= "'" & PassExp.Text & "', "
SqlUpdate &= "'" & VisaExp.Text & "', "
SqlUpdate &= "'No Visa', "
SqlUpdate &= "'" & WorkerID_.Text & "') "
Dim insertCommand As New OleDbCommand(SqlUpdate, con.oleconnection)
Dim cmd1 As New OleDbCommand(InsertSQL, con.oleconnection)
Try
con.open()
cmd1.ExecuteNonQuery()
insertCommand.ExecuteNonQuery()
Catch
FailureText.Text = "Unable to add user"
Finally
con.close()
End Try
End If
Response.Redirect("Workers.aspx")
End Sub
the Insert into login part is working. the data is well inserted. but for the insert into worker part is not working. the data is not inserted into the table. the program shows no error and it still can work. what could possibly wrong with this?
Read another answer on OleDb I just answered on another post. You will be wide open to sql-injection too. Parmaeterize queries. By you concatenating strings to build one command, what if one value has a single-quote within the text entry. You are now hosed. What if someone puts malicious SQL commands and then deletes your records or entire table(s). Learn to parameterize your queries and also clean values, especially if coming from a web interface.
Your commands should probably be updated something like
Dim con As dbConn = New dbConn()
Dim SqlSelect As String
SqlSelect = "SELECT * FROM login Where user_id= #parmUserID"
Dim cmd As New OleDbCommand(SqlSelect, con.oleconnection)
cmd.Parameters.AddWithValue( "parmUserID", WorkerID_.Text )
Follow-suit with the Insert and update commands... parameterize them but using #variable place-holders in your commands.
Dim InsertSQL As String
InsertSQL = "INSERT INTO login (user_id, user_role, user_password, user_status) "
InsertSQL &= " VALUES ( #parmUser, #parmRole, #parmPwd, #parmStatus )"
Dim cmdInsert As New OleDbCommand(InsertSQL, con.oleconnection)
cmdInsert.Parameters.AddWithValue( "parmUser", WorkerID_.Text )
cmdInsert.Parameters.AddWithValue( "parmRole", "Worker" )
cmdInsert.Parameters.AddWithValue( "parmPwd", "12345" )
cmdInsert.Parameters.AddWithValue( "parmStatus", 1 )
Dim SqlUpdate As String
SqlUpdate = "INSERT INTO Worker (ID, WorkerID, WorkerName, DoB, Address, Phone, Email, CompanyName, PassportNum, PassportExp, VisaExp, VisaStatus, user_id) "
SqlUpdate &= " VALUES ( #parmID, #parmName, #parmDoB, etc... ) "
Dim cmdUpdate As New OleDbCommand(SqlUpdate, con.oleconnection)
cmdUpdate.Parameters.AddWithValue( "parmID", WorkerID_.Text )
cmdUpdate.Parameters.AddWithValue( "parmName", WorkerName.Text )
cmdUpdate.Parameters.AddWithValue( "parmDoB", DoB.Text )
-- etc with the rest of the parameters.
Final note. Make sure the data types you are trying to insert or update are of same type expected in the table. Such example is your "Birth Date" (DoB) field. If you are trying to insert as simple text, and it is not in an auto-converted format, the SQL-Insert might choke on it and fail. If you have a textbox bound to a DateTime type, then your parameter might be Dob.SelectedDate (such as a calendar control), or you could pre-convert from text to a datetime and then use THAT as your parameter value.
Other numeric values, leave as they are too, they should directly apply for the insert. You could also identify the AddWithValue() call the data type the parameter should represent (string, int, double, datetime, whatever)
You seem to have 12 parameters you wish to insert, and 13 arguments in the VALUES part of your insert query. is the Default seen in the values section below intentional?
INSERT INTO Worker (ID, ... VisaStatus) VALUES (default,"
ensure you have the correct number of parameters defined and added, then let us know, but i could be missing something else.

check the update command, m i doing mistake in its syntax?

his there all,
i'm working on a cms, while trying the update command to update the records, its not working.
here's m complete code for update,
Dim ID, RegNo, BedNo, BedType, Charges, PatName, PatAge, PatAddr, Phone, CheckupDate, Disease, BloodGroup, Doctor, Remarks As String
RegNo = txtRegNo.Text
BedNo = CmbBedNo.SelectedItem.ToString()
BedType = CmbBedType.SelectedItem.ToString()
Charges = txtCharges.Text
PatName = txtPatName.Text
PatAge = txtPatAge.Text
PatAddr = txtPatAdd.Text
Phone = txtPhone.Text
CheckupDate = txtDate.Text
Disease = txtDisease.Text
BloodGroup = cmbBloodGrp.SelectedItem.ToString()
Doctor = cmbDoctor.SelectedItem.ToString()
Remarks = txtRemarks.Text
ID = txtRegNo.Text
Dim conStudent As New OleDbConnection
Dim comStudent As New OleDbCommand
conStudent.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\DBProject\hspms.mdb"
conStudent.Open()
comStudent.CommandText = "UPDATE AdmitPt SET ID =" & ID & ", Bedcategory='" & BedType & "', BedNo=" & BedNo & ", BedCharges=" & Charges & ", PtName='" & PatName & "', PtAge=" & PatAge & ", Address='" & PatAddr & "', PhoneNo='" & Phone & "', Dates='" & CheckupDate & "', Disease='" & Disease & "', BloodGroup='" & BloodGroup & "', Doctor='" & Doctor & "', Remarks='" & Remarks & "' WHERE ID=" & RegNo
comStudent.Connection = conStudent
comStudent.CommandType = CommandType.Text
If (comStudent.ExecuteNonQuery() > 0) Then
MsgBox("record successfully updated")
End If
conStudent.Close()
one thing, that the fields named with ID, BedNo, BedCharges, Age are set to Number as data type.
First of all, switch to a parameterized query. This will remove any possibilities of Sql Injection, but also avoid the problems with quoting strings, parsing decimal numbers and dates
Dim conString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=F:\DBProject\hspms.mdb"
Dim cmdText = "UPDATE AdmitPt SET ID =?, Bedcategory=?, BedNo=?, BedCharges=?, " & _
"PtName=?, PtAge=?, Address=?, PhoneNo=?, Dates=?, Disease=?, " & _
"BloodGroup=?, Doctor=?, Remarks=? WHERE ID=?"
Using conStudent = new OleDbConnection(conString)
Using comStudent = new OleDbCommand(cmdText, conStudent)
conStudent.Open()
comStudent.Parameters.AddWithValue("#p1", Convert.ToInt32(ID))
comStudent.Parameters.AddWithValue("#p2", BedType)
comStudent.Parameters.AddWithValue("#p3", Convert.ToInt32(BedNo))
comStudent.Parameters.AddWithValue("#p4", Convert.ToDecimal(Charges))
.... and so on for every other question marks in the cmdText ....
.... respecting the exact order of the fields ...................
.... try also to pass the correct datatype for every non string field
If (comStudent.ExecuteNonQuery() > 0) Then
MsgBox("record successfully updated")
End If
End Using
End Using