복붙노트

[SQL] 어떻게 매개 변수화 된 SQL 쿼리를 만들려면 어떻게해야합니까? 왜해야 내가?

SQL

어떻게 매개 변수화 된 SQL 쿼리를 만들려면 어떻게해야합니까? 왜해야 내가?

나는 "모두가"사용자 입력의 모든 조각을 vailidate하지 않고 SQL 주입 공격으로부터 보호하기 위해 매개 변수화 된 SQL 쿼리를 사용하고 있다고 들었습니다.

당신이 어떻게해야합니까? 당신은 저장 프로 시저를 사용하는 경우 자동으로받을 수 있나요?

내이를 이해하는 것은 비 파라미터입니다 그래서 :

cmdText = String.Format("SELECT foo FROM bar WHERE baz = '{0}'", fuz)

이것은 매개 변수화 할 것인가?

cmdText = String.Format("EXEC foo_from_baz '{0}'", fuz)

또는 내가 SQL 주입으로부터 자신을 보호하기 위해이 같은보다 광범위한 일을 어떻게해야합니까?

With command
    .Parameters.Count = 1
    .Parameters.Item(0).ParameterName = "@baz"
    .Parameters.Item(0).Value = fuz
End With

다른 장점은 보안 고려 사항 외에 매개 변수화 된 쿼리를 사용하여이 있습니까?

업데이트 :이 위대한 문서는 Grotok하여 질문 참조 중 하나에 연결되었다. http://www.sommarskog.se/dynamic_sql.html

해결법

  1. ==============================

    1.귀하의 EXEC 예 매개 변수화되지 않습니다. 당신은 손상을 초래에서이 같은 입력을 방지하기 위해 매개 변수가있는 쿼리 (일부 서클 준비된 문)가 필요합니다 :

    귀하의 EXEC 예 매개 변수화되지 않습니다. 당신은 손상을 초래에서이 같은 입력을 방지하기 위해 매개 변수가있는 쿼리 (일부 서클 준비된 문)가 필요합니다 :

    당신의 fuz 변수에 그 퍼팅 시도 (또는 당신이 당신의 바 테이블을 소중히하는 경우,하지 않습니다). 더 미묘하고 손상 쿼리도 가능합니다.

    여기에서 SQL 서버와 매개 변수를 어떻게의 예입니다 :

    Public Function GetBarFooByBaz(ByVal Baz As String) As String
        Dim sql As String = "SELECT foo FROM bar WHERE baz= @Baz"
    
        Using cn As New SqlConnection("Your connection string here"), _
            cmd As New SqlCommand(sql, cn)
    
            cmd.Parameters.Add("@Baz", SqlDbType.VarChar, 50).Value = Baz
            Return cmd.ExecuteScalar().ToString()
        End Using
    End Function
    

    저장 프로 시저를 종종 SQL 주입을 방지 적립된다. 그러나, 대부분의 시간은 여전히 ​​쿼리 매개 변수를 사용하여 전화를해야하거나 도움이되지 않습니다. 당신이 독점적으로 저장 프로 시저를 사용하는 경우, 당신은 응용 프로그램 사용자 계정 (모든 걸하지만 EXEC에 대해) 등, DELETE, CREATE, SELECT, UPDATE, ALTER 권한을 끄고 몇 가지 보호 방법이를 얻을 수 있습니다.

  2. ==============================

    2.확실히 마지막, 즉

    확실히 마지막, 즉

    매개 변수화 된 쿼리는 두 가지 장점이 있습니다 :

  3. ==============================

    3.당신이 진정으로 매개 변수화되는 유일한 사람이기 때문에 마지막 예제로 가고 싶어. 게다가 보안 문제 (이 훨씬 더 널리 당신이 생각하는 것입니다) 당신이 전달되는 값이 아닌지 각각의 유형을 검사하지 않고 주변에 작은 따옴표를 요구하는 경우 당신은 확신 할 수 없기 때문에 매개 변수화를 처리 ADO.NET을하게하는 것이 가장 좋습니다 매개 변수입니다.

    당신이 진정으로 매개 변수화되는 유일한 사람이기 때문에 마지막 예제로 가고 싶어. 게다가 보안 문제 (이 훨씬 더 널리 당신이 생각하는 것입니다) 당신이 전달되는 값이 아닌지 각각의 유형을 검사하지 않고 주변에 작은 따옴표를 요구하는 경우 당신은 확신 할 수 없기 때문에 매개 변수화를 처리 ADO.NET을하게하는 것이 가장 좋습니다 매개 변수입니다.

    [편집 여기서 예이다 :

    SqlCommand command = new SqlCommand(
        "select foo from bar where baz = @baz",
        yourSqlConnection
    );
    
    SqlParameter parameter = new SqlParameter();
    parameter.ParameterName = "@baz";
    parameter.Value = "xyz";
    
    command.Parameters.Add(parameter);
    
  4. ==============================

    4.대부분의 사람들은 PHP의 PDO 또는 Perl DBI와 같은 서버 측 프로그래밍 언어의 라이브러리를 통해이 작업을 수행 할 것입니다.

    대부분의 사람들은 PHP의 PDO 또는 Perl DBI와 같은 서버 측 프로그래밍 언어의 라이브러리를 통해이 작업을 수행 할 것입니다.

    예를 들어, PDO에서 :

    $dbh=pdo_connect(); //you need a connection function, returns a pdo db connection
    
    $sql='insert into squip values(null,?,?)';
    
    $statement=$dbh->prepare($sql);
    
    $data=array('my user supplied data','more stuff');
    
    $statement->execute($data);
    
    if($statement->rowCount()==1){/*it worked*/}
    

    이 데이터베이스 삽입 데이터를 탈출을 담당한다.

    하나의 장점은 속도의 이점을 얻고, 하나의 준비된 문을 삽입 여러 번 반복 할 수 있다는 것입니다.

    예를 들어, 위의 쿼리에서 나는 데이터의 무리의 데이터 배열을 만드는 동안 한 번 문, 다음 루프를 준비하고를 반복 할 수 - 필요에 따라> 여러 번 실행합니다.

  5. ==============================

    5.귀하의 명령 텍스트처럼해야합니다

    귀하의 명령 텍스트처럼해야합니다

    cmdText = "SELECT foo FROM bar WHERE baz = ?"
    
    cmdText = "EXEC foo_from_baz ?"
    

    그런 다음 매개 변수 값을 추가합니다. fuz 변수로 설정되면 값 콘 만 결국 것을 보장하지만이 방법은 다른 방법으로, 반면에 값으로 사용되고

    "x'; delete from foo where 'a' = 'a"
    

    당신은 일어날 일에 볼 수 있습니까?

  6. ==============================

    6.다음은 SQL로 시작하는 짧은 클래스 그리고 당신은 거기에서 구축하고 클래스에 추가 할 수 있습니다.

    다음은 SQL로 시작하는 짧은 클래스 그리고 당신은 거기에서 구축하고 클래스에 추가 할 수 있습니다.

    MySQL의

    Public Class mysql
    
        'Connection string for mysql
        Public SQLSource As String = "Server=123.456.789.123;userid=someuser;password=somesecurepassword;database=somedefaultdatabase;"
    
        'database connection classes
    
        Private DBcon As New MySqlConnection
        Private SQLcmd As MySqlCommand
        Public DBDA As New MySqlDataAdapter
        Public DBDT As New DataTable
        Public BindSource As New BindingSource
        ' parameters
        Public Params As New List(Of MySqlParameter)
    
        ' some stats
        Public RecordCount As Integer
        Public Exception As String
    
        Function ExecScalar(SQLQuery As String) As Long
            Dim theID As Long
            DBcon.ConnectionString = SQLSource
            Try
                DBcon.Open()
                SQLcmd = New MySqlCommand(SQLQuery, DBcon)
                'loads params into the query
                Params.ForEach(Sub(p) SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value))
    
                'or like this is also good
                'For Each p As MySqlParameter In Params
                ' SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value)
                ' Next
                ' clears params
                Params.Clear()
                'return the Id of the last insert or result of other query
                theID = Convert.ToInt32(SQLcmd.ExecuteScalar())
                DBcon.Close()
    
            Catch ex As MySqlException
                Exception = ex.Message
                theID = -1
            Finally
                DBcon.Dispose()
            End Try
            ExecScalar = theID
        End Function
    
        Sub ExecQuery(SQLQuery As String)
    
            DBcon.ConnectionString = SQLSource
            Try
                DBcon.Open()
                SQLcmd = New MySqlCommand(SQLQuery, DBcon)
                'loads params into the query
                Params.ForEach(Sub(p) SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value))
    
                'or like this is also good
                'For Each p As MySqlParameter In Params
                ' SQLcmd.Parameters.AddWithValue(p.ParameterName, p.Value)
                ' Next
                ' clears params
    
                Params.Clear()
                DBDA.SelectCommand = SQLcmd
                DBDA.Update(DBDT)
                DBDA.Fill(DBDT)
                BindSource.DataSource = DBDT  ' DBDT will contain your database table with your records
                DBcon.Close()
            Catch ex As MySqlException
                Exception = ex.Message
            Finally
                DBcon.Dispose()
            End Try
        End Sub
        ' add parameters to the list
        Public Sub AddParam(Name As String, Value As Object)
            Dim NewParam As New MySqlParameter(Name, Value)
            Params.Add(NewParam)
        End Sub
    End Class
    

    MS SQL / 익스프레스

    Public Class MSSQLDB
        ' CREATE YOUR DB CONNECTION
        'Change the datasource
        Public SQLSource As String = "Data Source=someserver\sqlexpress;Integrated Security=True"
        Private DBCon As New SqlConnection(SQLSource)
    
        ' PREPARE DB COMMAND
        Private DBCmd As SqlCommand
    
        ' DB DATA
        Public DBDA As SqlDataAdapter
        Public DBDT As DataTable
    
        ' QUERY PARAMETERS
        Public Params As New List(Of SqlParameter)
    
        ' QUERY STATISTICS
        Public RecordCount As Integer
        Public Exception As String
    
        Public Sub ExecQuery(Query As String, Optional ByVal RunScalar As Boolean = False, Optional ByRef NewID As Long = -1)
            ' RESET QUERY STATS
            RecordCount = 0
            Exception = ""
            Dim RunScalar As Boolean = False
    
            Try
                ' OPEN A CONNECTION
                DBCon.Open()
    
                ' CREATE DB COMMAND
                DBCmd = New SqlCommand(Query, DBCon)
    
                ' LOAD PARAMS INTO DB COMMAND
                Params.ForEach(Sub(p) DBCmd.Parameters.Add(p))
    
                ' CLEAR PARAMS LIST
                Params.Clear()
    
                ' EXECUTE COMMAND & FILL DATATABLE
                If RunScalar = True Then
                    NewID = DBCmd.ExecuteScalar()
                End If
                DBDT = New DataTable
                DBDA = New SqlDataAdapter(DBCmd)
                RecordCount = DBDA.Fill(DBDT)
            Catch ex As Exception
                Exception = ex.Message
            End Try
    
    
            ' CLOSE YOUR CONNECTION
            If DBCon.State = ConnectionState.Open Then DBCon.Close()
        End Sub
    
        ' INCLUDE QUERY & COMMAND PARAMETERS
        Public Sub AddParam(Name As String, Value As Object)
            Dim NewParam As New SqlParameter(Name, Value)
            Params.Add(NewParam)
        End Sub
    End Class
    
  7. from https://stackoverflow.com/questions/542510/how-do-i-create-a-parameterized-sql-query-why-should-i by cc-by-sa and MIT license