Search code examples
mysqlsqlvb.netparameterized

Parameterize SQL Queries


I want parameterize some SQL Statements so my code isn't vunerable to SQL Injections any longer But i have actually no plan how to parameterize for example a where clause.

Dim accID As String = DatabaseConnecter.readField("SELECT ID FROM accounts WHERE accountname ='" & user & "' AND password='" & pw & "';")

The Problem is if you type in a given username, for example test and extend the username with. You can log in without entering the password into the Application.

Edit:

Public Function readField(ByVal sql As String) As String
        Dim output As String = "ERROR"
        Using cn = New MySqlConnection(connString.ToString())
            Using cmd = New MySqlCommand(sql, cn)
                cn.Open()
                Using rd = cmd.ExecuteReader()
                    Try
                        rd.Read()
                        output = rd.GetString(0)
                        rd.Close()
                    Catch ex As Exception
                    End Try
                End Using
                cn.Close()
            End Using
        End Using
        Return output
    End Function
´´´

Solution

  • To have a parameterized query you need to create parameters and write a proper SQL text where, in place of values typed directly from your user, you have parameter placeholders.

    So, for example, you sql text should be something like this

    Dim sqlText = "SELECT ID FROM accounts WHERE accountname =@name AND password=@pwd"
    

    Now you have a parameterized text, but stil we need to create the parameters that will be sent to the database engine together with your sql command.

    You can create the parameter (two in this case) in this way before calling the method that executes the query

    Dim p1 as MySqlParameter = new MySqlParameter("@name", MySqlDbType.VarChar)
    p1.Value = user  
    
    Dim p2 as MySqlParameter = new MySqlParameter("@pwd", MySqlDbType.VarChar)
    p2.Value = password
    
    Dim pms As List(Of MySqlParameter) = new List(Of MySqlParameter)()
    pms.Add(p1)
    pms.Add(p2)
    

    Now we need to pass this list to your method (and this requires changes to your method signature)

    DatabaseConnecter.readField(sqlText, pms)
    

    The method itself should change to something like

    Public Function readField(ByVal sql As String, Optional pms As List(Of MySqlParameter) = Nothing) As String
        Dim output As String = "ERROR"
        Using cn = New MySqlConnection(connString.ToString())
            Using cmd = New MySqlCommand(sql, cn)
                cn.Open()
    
                ' This block adds the parameter defined by the caller to the command
                ' The parameters are optional so we need to check if we have really received the list or not
                if pms IsNot Nothing Then
                    cmd.Parameters.AddRange(pms.ToArray())
                End If
                Using rd = cmd.ExecuteReader()
                    Try
                        rd.Read()
                        output = rd.GetString(0)
                        rd.Close()
                    Catch ex As Exception
                    End Try
                End Using
                ' no need to close when inside a using block
                ' cn.Close()
            End Using
        End Using
        Return output
    End Function
    

    The method now has an optional parameter that will contain the list of the parameters required by the query (or nothing if your query doesn't require parameters). This list is added to the command parameters collection and the query is now executed.

    Final Note: Storing passwords in clear text into a database is a well known security problem. I suggest you to search about how to store passwords in a database.