Parametrize Queries to prevent SQL Injection - sql

I know that I need to Parametrize my queries, mainly for safety reasons, and I need help doing so. I'm using VB in visual studio 2012 and SQL Server 2012. I have never done this before and everything I find on the web seems unsuited to my particular code. The bit that I think needs work is the following:
objconnection.Open()
strSQL = "insert into dbo.Event(ID, Name, Summary, Date) values (NEWID(), '" & strName & "','" & strSummary & "','" & strLocation & "','" & strDate & "')"
objcmd = New OleDbCommand(strSQL, objconnection)
objcmd.ExecuteNonQuery()
objconnection.Close()
MsgBox("Event Created", vbMsgBoxSetForeground)
Any pointers greatly appreciated. If you need more of the code let me know!
From comments:
I did look at that and tried it but I had problems. At this part:
.add(new SqlParameter("#strname", '"& strName &"'))
the , between the "#streventname" and '"strName"' is underlined and it says Expression expected.
Also
Dim cmd As SqlCommand = New SqlCommand(cmdText, objconnection)
objconnection gets an error "Value of type 'System.Data.OleDb.OleDbConnection' cannot be converted to 'System.Data.SqlClient.SqlConnection'.
Probably something stupid I've missed out.

You are mixing your SQL-Objects with your OLEDB-Objects. Looks like you are using an OLEDB connection, so that means you have to use OLEDB-Objects, so use OleDbCommand instead of SqlCommand, etc.
Your parameter line should look something like this:
.add(new OleDbParameter("#strname", strName))
For OleDB queries, it is important to realize that the parameters are actually ignoring the name #strname and just updating the parameter information in index order. So the order in which the parameters appear in the sql statement have to be in the same order you supply the parameters.

Thanks you for all the help. I managed to solve it. This is what I now have if anyone is interested.
Imports System
Imports System.Data
Imports System.Data.OleDb
Imports System.Data.SqlClient
Partial Class _Default
Inherits System.Web.UI.Page
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim strName As String = Request.Form("txtName")
Dim strSummary As String = Request.Form("txtSummary")
Dim strDate As String = Request.Form("txtDate")
Dim objconnection As OleDbConnection = Nothing
Dim objcmd As OleDbCommand = Nothing
Dim strconnection As String, strSQL As String
strconnection = "provider=SQLOLEDB;data source=XXX;database=Events;uid=XXX;pwd=XXX;"
objconnection = New OleDbConnection(strconnection)
objconnection.ConnectionString = strconnection
objconnection.Open()
strSQL = "insert into dbo.CreateApp(ID, Name, Summary, Date)values(NEWID(), ?, ?, ?)"
objcmd = New OleDbCommand(strSQL, objconnection)
objcmd.Parameters.Add(New System.Data.OleDb.OleDbParameter("#Name", strName))
objcmd.Parameters.Add(New System.Data.OleDb.OleDbParameter("#Summary", strSummary))
objcmd.Parameters.Add(New System.Data.OleDb.OleDbParameter("#Date", strDate))
objcmd.ExecuteNonQuery()
objconnection.Close()
End Sub
End Class
The key was putting in ?s.

I agree with Lars except you are missing the fact that the sql is wrong. Here is a more complete example.
Dim sql = <value>insert into dbo.Event(ID, Name, Summary, Date) values (NEWID(),#Name,#Summary,#Date)</value>
Using connection As OleDb.OleDbConnection(connectionString)
Using command As New OleDb.OleDbCommand(sql.Value, connection)
command.Parameters.AddWithValue("#Name", nameValue)
command.Parameters.AddWithValue("#Summary", summaryValue)
command.Parameters.AddWithValue("#Date", DateValue)
command.ExecuteNonQuery()
End Using
End Using
If you want to not bother with ADO and are looking for something simpler I recommend using Simple.Data http://simplefx.org/simpledata/docs/. It is by far one of the simplest ways to interact with a database without having to now SQL or ADO but it certainly does help.
Good Luck

Related

Selecting specific table from database VB

Public Sub UserList_SelectedIn(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles UserList.SelectedIndexChanged
Dim provider As String
Dim dataFile As String
Dim connString As String
Dim myConnection As OleDbConnection = New OleDbConnection
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source ="
dataFile = "\users.accdb"
connString = provider & dataFile
myConnection.ConnectionString = connString
myConnection.Open()
Chart1.Series.Add("Score") 'Adds the graph into the program
Dim cmdd As OleDbCommand = New OleDbCommand("SELECT [Score], [Month] FROM * WHERE Table ='" & UserList.SelectedItem, myConnection)
Dim dr2 As OleDbDataReader = cmdd.ExecuteReader
While dr2.Read
Chart1.Series("Score").Points.AddXY(dr2("Month").ToString, dr2("Score").ToString) 'Adds the month/score to the graph
End While
End Sub
Trying to find a way to make the following line of code allow me to select data from a specific table that the user can choose from a listbox.
Dim cmdd As OleDbCommand = New OleDbCommand("SELECT [Score] FROM * WHERE Table ='" & UserList.SelectedItem, myConnection)
It gives the error when running: Syntax error in FROM clause.
I'm guessing it's because of the * after FROM.
This should be a comment but I need 50+ rep to comment... but it should show you how to structure your query
SELECT [column] FROM [table] WHERE [condition]
I was just about to add comment to say you need another " ' " at the end of the command, but also, I've never seen FROM * used in a command like that. Not saying it's wrong, I just have never seen it :). Anyways, this should help out with the issue, dont forget to bracket tables and fields if they contain wildcards or spaces in the names. Brackets can be used even if do not contain spaces or wildcards.
Public Sub UserList_SelectedIn(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles UserList.SelectedIndexChanged
Dim provider As String
Dim dataFile As String
Dim connString As String
Dim myConnection As OleDbConnection = New OleDbConnection
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source ="
dataFile = "\users.accdb"
connString = provider & dataFile
myConnection.ConnectionString = connString
myConnection.Open()
Chart1.Series.Add("Score") 'Adds the graph into the program
Dim Table_Str As String = "[" & UserList.SelectedItem & "]"
Dim cmdd As OleDbCommand = New OleDbCommand("SELECT [Score], [Month] FROM " & Table_Str, myConnection)
Dim dr2 As OleDbDataReader = cmdd.ExecuteReader
While dr2.Read
Chart1.Series("Score").Points.AddXY(dr2("Month").ToString, dr2("Score").ToString) 'Adds the month/score to the graph
End While
End Sub
You can also add in If statements or error checking before running the code to make sure a selection has been made from the user.
Hth
Chicken
Turning on Option Strict will force you to use .ToString .SelectedItem is an object and Option Strict requires an explicit conversion. Not too many extra keystrokes but it could save your runtime errors.
Dim cmdd As OleDbCommand = New OleDbCommand("SELECT [Score], [Month] FROM [" & ListBox1.SelectedItem.ToString & "]", myConnection)
Laziness will do you no good. You should try to write all the table names after the FROM clause. Maybe that will solve it.

ASP.NET(VB) How to insert textbox.text into SQL database?

I am designing a register form.
The following is my codes:
but after I do it, then the SQL table display is not the user's data....?
The database table display &username&, &password&
(username, password...are textboxes name)
Protected Sub btnOK_Click(sender As Object, e As EventArgs) Handles btnOK.Click
Dim Conn As SqlConnection = New SqlConnection(".....")
Conn.Open()
Dim sqlstr As String = "Insert Into user_profile(username,password,nickname,realname,email) Values('" & username.Text & "','" & password.Text & "','" & nickname.Text & "','" & realname.Text & "','" & email.Text & "')"
Dim cmd As New SqlCommand(sqlstr, Conn)
cmd.ExecuteNonQuery()
cmd.Cancel()
Conn.Close()
Conn.Dispose()
End Sub
Ok, first, I'll take a stab at your question. Then, we NEED to talk about SQL Injections.
Try this:
Dim MyValues as String = String.Format("'{0}', '{1}', '{2}', '{3}', '{4}'", username.Text, password.Text, nickname.Text, realname.Text, email.Text )
Dim sqlstr As String = "Insert Into user_profile(username,password,nickname,realname,email) Values(MyValues)"
(I've not tested that code. Watch for syntax errors.)
Now, that having been said, it is VITAL that you understand the danger of the way you are trying to do this. The serious problem here is that you are wide open to a SQL Injection attack. Google it. But in short, using this approach, someone can put commands like 'drop table' into your textbox, and those commands will be executed in your database.
The proper way to do this would be to create a stored procedure that contains the INSERT statement, and then pass your values to it with parameters. The web is littered with tutorials on how to do this. You'll find one easy enough.
Good luck!

Query SQL Database and Store Results in a Variable VB.Net

I am trying to query a SQL DB using a textbox field and retreive a column from the DB and store it in a variable so I can use it in other places within my site. My web form requires the user to enter a few items such as name and zip code.
My database has 3 columns; email address, zip code, and id. I need the input form to query the database and return the "email address" that matches the user's inputted "zip code"
I understand the SQL SELECT statement and the connection string is correct. My queries are working, I just can't seem to figure out how to get the returned "email address" to store in a variable. Any help would be appreciated.
Dim strconnection As String, strSQL As String, strZipCheck As String
Dim objconnection As OleDbConnection = Nothing
Dim objcmd As OleDbCommand = Nothing
Dim RREmail As String = Nothing
Dim zipQuery As String = zipCodeBox.Text
'connection string
strconnection = "provider=SQLOLEDB;Data Source=XXX.XXX.XXX.XXX;Initial Catalog=XXXXXXX;User ID=XXXX;Password=XXXXXXXX;"
objconnection = New OleDbConnection(strconnection)
objconnection.ConnectionString = strconnection
'opens connection to database
objconnection.Open()
strSQL = "SELECT [EMAIL ADDRESS] FROM ZIPCODEDATA WHERE [ZIP CODE] = #ZIP CODE "
objcmd = New OleDbCommand(strSQL, objconnection)
RREmail = CType(objcmd.ExecuteScalar(), String)
lblRREmail.Text = RREmail
objconnection.Close()
While the other comments do point out particular deficiencies with your syntax, I would like to address the question of storing a variable and take it a bit further. I generally do not use parameterized connections unless I am calling stored procedures and need an output parameter. Instead, here is what I often do to create a database connection and get my results.
First I create a public class called dbConn so I dont have to write it out a million times.
Imports System.Data.SqlClient
Public Class dbConn
Public Property strSQL As String
Private objConn As SqlClient.SqlConnection = _
New SqlClient.SqlConnection("Data Source=(local)\dev;Initial Catalog=testDataBase;Persist Security Info=False;Integrated Security = true;")
Public Function getDt() As DataTable
Dim Conn As New SqlClient.SqlConnection
Dim da As SqlClient.SqlDataAdapter
Dim dt As New DataTable
Try
objConn.Open()
da = New SqlClient.SqlDataAdapter(strSQL, objConn)
da.Fill(dt)
da = Nothing
objConn.Close()
objConn = Nothing
Catch ex As Exception
objConn.Close()
objConn = Nothing
End Try
Return dt
End Function
End Class
Then from another class (lets assume its form1) I call up that function to get a datatable returned to me. In this case I select TOP 1 to save your sanity in case by chance there is more than one email address per zip code.
Public sub getdata()
Dim strEmailAddress As String = Nothing
Dim dt As New DataTable
Dim da As New dbConn
da.strSQL = " select top 1 [email address] from [zipcode] " _
& " where [zip code] = '" & strZipCode & "'" _
& " order by [email address] asc"
dt = da.getDt
If dt.Rows.Count > 0 Then
If Not IsDBNull(dt.Rows(0)(0).ToString) Then
strEmailAddress = dt.Rows(0)(0).ToString
End If
End If
End Sub
From there you can use strEmailAddress within the sub after it is set, or you can move the string declaration outside of the sub as a public string declaration to use it elsewhere, or you can create other classes like an email class with a public property for strEmailAddress to pass it off to, etc.
I hope something in there helps you understand how to deal with your problem.

Vb.Net Windows Form Search Access Database

Ok, hopefully I explain this correctly. I have had about 3 months professional experience working with Access databases, and none with Vb.net, but I am working on a project to get my degree. The goal of this project was to create a Windows Form for my parent's company, All Keyed Up Lock & Safe.
This form was going to link to an Access database with 4 tables that was a listing of some of the company's customers. The form would then allow you to search that database for a specific customer and then return all the information on that specific customer.
This would be useful for billing and also would let us view any special notes we have on the customer before leaving. The four tables are [McDonald's-Corporate Stores], [McDonald's-Independently Owned], [Sonic-Corporate Stores], [Sonic-Independently Owned].
Basically the problem I am having is with the search function. I cannot for the life of me figure out a way to get this to work. I have tried 4 or 5 different solutions and still nothing. I am using Visual Studio 2013. Here is my code I have at the moment, for the search button:
Private Sub SearchButton_Click(sender As Object, e As EventArgs) Handles SearchButton.Click
Dim Connection As New SqlClient.SqlConnectionStringBuilder
Connection.DataSource = "file:///C:\Users\thelukester145\Documents\All%20Keyed%20Up\All%20Keyed%20Up,%20Lock%20&%20Safe,%20LLC.accdb"
Dim objSQLConnection = New SqlClient.SqlConnection(Connection.ConnectionString)
Dim cmd As New SqlCommand()
Dim myTable As New DataTable()
Dim SearchFor = SearchBox.Text
If AddressButton.Checked Then
cmd.Connection = objSQLConnection
cmd.CommandText = "SELECT * FROM [McDonald's-Corporate Stores] WHERE [Address] LIKE '%" & SearchFor & "%'"
Dim myAdapter As New SqlDataAdapter(cmd)
myAdapter.Fill(myTable)
DataGrid.DataGridView1.DataSource = myTable
ElseIf NumberButton.Checked Then
cmd.Connection = objSQLConnection
cmd.CommandText = "SELECT * FROM [McDonald's-Corporate Stores] WHERE [McOpCo#] LIKE '%" & SearchFor & "%'"
Dim myAdapter As New SqlDataAdapter(cmd)
myAdapter.Fill(myTable)
DataGrid.DataGridView1.DataSource = myTable
End If
DataGrid.Show()
End Sub
As you can see I have just been trying to get this to work for just one table and can't even do that. I would prefer not to use the datagrid method to display the information but rather display it in textboxes that are positioned on the form.
Anyways any help would be MUCH appreciated and sorry for such a long question.
Where are you opening the connection. Can you try the following code to establish a connection:
Dim cnnOLEDB As New OleDbConnection
Dim cmdOLEDB As New OleDbCommand
Dim strConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & System.Environment.CurrentDirectory & "\URDataBaseName.mdb"
cnnOLEDB.ConnectionString = strConnectionString
cnnOLEDB.Open()
' your code goes here
cnnOLEDB.Close()

vb.net generalized write of data to excel

I need to create an excel file from scratch in VB.NET given a DataTable from asp.net.
I can do this for a specific file, but I don't know how to do it for a general database.
That is, where I use the "CREATE TABLE ..." I don't know how to tell it what types to use for the data in the table.
The DataTable is derived from a FoxPro database. (I don't know if that matters.)
I invoke the table similar to as follows:
<%
return_value = make_excel( sql_table, excel_filename)
%>
make_excel is defined as
Option Explicit On
'Option Strict On
Imports System
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.Page
Imports System.IO
Imports Microsoft.VisualBasic
Imports System.Diagnostics
Imports System.Data
Imports System.Data.OleDb
Public Class clsCommon
Inherits Page
' buncha other stuff defined in here.
Public Shared Function make_excel(ByVal sqlTable As DataTable, ByVal xls_fn As String) As Boolean
Dim conn As System.Data.OleDb.OleDbConnection
Dim ds As System.Data.DataSet
Dim cmd As New System.Data.OleDb.OleDbCommand()
conn = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & xls_fn & "';Extended Properties=Excel 8.0;")
conn.Open()
cmd.Connection = conn
cmd.CommandText = "CREATE TABLE MyTable ( Admin char(20), first_name char(20));"
cmd.ExecuteNonQuery()
cmd.CommandText = "INSERT INTO MyTable ( Admin, first_name ) VALUES ('true', 'Bob')"
cmd.ExecuteNonQuery()
conn.Close()
Return True
End Function
End Class
What I need to be able to do is run through the values in sqlTable above, check their type and then build the sql to write them. Pointers?
Have you looked into the copyfromrecordset function? You'll need to do a bit of work and its a bit of a change of approach but it might be something you can look into. An MS article is available here (Sorry, the article is based around VBA, but it should help as a guide).
I have a solution to the problem. I'm not happy about it as a general solution, but it works well enough for the cases I'm currently dealing with.
In this solution, I create a template of the excel file that has the column headings I want to use. When I do the select in the forward code, I change the name of the fields as appropriate (or drop whatever fields I don't want).
Public Shared Function TestXL(ByVal resp As HttpResponse, ByVal sqlTable As DataTable, ByVal xls_template_fn As String, ByVal xls_fn As String) As Boolean
Dim conn As System.Data.OleDb.OleDbConnection
Dim ds As System.Data.DataSet
Dim cmd As New System.Data.OleDb.OleDbCommand()
Dim r As DataRow
Dim c As DataColumn
Dim i As Integer
Dim sql As String
dim str as string
If File.Exists(xls_template_fn) Then
try
If File.Exists(xls_fn) Then
File.Delete(xls_fn)
Else
File.Copy(xls_template_fn, xls_fn)
End If
catch ex1 as Exception
File.Copy(xls_template_fn, xls_fn)
End Try
Else
resp.Write("Unable to locate template file: " & xls_template_fn)
Return False
End If
conn = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & xls_fn & "';Extended Properties=Excel 8.0;")
conn.Open()
cmd.Connection = conn
cmd.CommandText = sql
For Each r In sqlTable.Rows
sql = "INSERT INTO MyTable ("
For i = 0 To sqlTable.Columns.Count - 1
sql = sql & " " & sqlTable.Columns(i).ColumnName & ","
Next
sql = Left(sql, sql.Length - 1) & " ) VALUES ( "
For i = 0 To sqlTable.Columns.Count - 1
str = r(i).toString()
dim str2 as string = str.replace("'", "''")
sql = sql & " '" & str2 & "',"
Next
sql = Left(sql, sql.Length - 1) & " );"
'resp.Write(sql & "<br/>")
cmd.CommandText = sql
cmd.ExecuteNonQuery()
Next
conn.Close()
Return True
End Function
Note the name of the the worksheet is the name of the table for the oledb call.
There's a link to other ways of doing this:
http://blogs.msdn.com/b/erikaehrli/archive/2009/01/30/how-to-export-data-to-excel-from-an-asp-net-application-avoid-the-file-format-differ-prompt.aspx
If I have to revisit this problem I'll probably start there.