“모든 사람”이 매개 변수화 된 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
답변
EXEC 예제는 매개 변수화되지 않습니다. 다음과 같은 입력으로 인한 손상을 방지하려면 매개 변수화 된 쿼리 (일부 서클의 준비된 문)가 필요합니다.
‘; DROP TABLE 막대;-
fuz 변수에 넣으십시오 (또는 막대 테이블을 중요하게 생각한다면하지 마십시오). 더 미묘하고 피해를주는 쿼리도 가능합니다.
다음은 SQL Server에서 매개 변수를 수행하는 방법의 예입니다.
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 삽입을 방지하는 것으로 간주됩니다. 그러나 대부분의 경우 여전히 쿼리 매개 변수를 사용하여 호출해야하거나 도움이되지 않습니다. 저장 프로 시저를 독점적으로 사용하는 경우 응용 프로그램 사용자 계정에 대한 SELECT, UPDATE, ALTER, CREATE, DELETE 등 (EXEC를 제외한 모든 항목)에 대한 권한을 해제하고 이러한 방식으로 보호를받을 수 있습니다.
답변
확실히 마지막 것, 즉
아니면 좀 더 광범위한 작업을해야합니까 …? (예,
cmd.Parameters.Add()
)
매개 변수화 된 쿼리에는 두 가지 주요 이점이 있습니다.
- 보안 : SQL 주입 취약점 을 피하는 좋은 방법입니다.
- 성능 : 다른 매개 변수를 사용하여 동일한 쿼리를 정기적으로 호출하는 경우 매개 변수화 된 쿼리를 통해 데이터베이스가 성능 향상의 상당한 원천 인 쿼리를 캐시 할 수 있습니다.
- 추가 : 데이터베이스 코드의 날짜 및 시간 형식 문제에 대해 걱정할 필요가 없습니다. 마찬가지로 코드가 영어가 아닌 로케일을 사용하는 시스템에서 실행되는 경우 소수점 / 소수점 쉼표에 문제가 없습니다.
답변
이것이 진정으로 매개 변수화되는 유일한 예제이므로 마지막 예제를 사용하고 싶습니다. 게다가 보안 문제 (이 훨씬 더 널리 당신이 생각하는 것입니다) 당신이에 전달하는 값이 주변 여부를 검사하지 않고 작은 따옴표가 필요한 경우 당신은 확신 할 수 없기 때문에 매개 변수화를 처리 ADO.NET을하게하는 것이 가장 좋습니다 Type
각 매개 변수를 .
[편집] 다음은 예입니다.
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);
답변
대부분의 사람들은 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*/}
이것은 데이터베이스 삽입을 위해 데이터를 이스케이프 처리합니다.
한 가지 장점은 하나의 준비된 문장으로 삽입을 여러 번 반복 할 수있어 속도 이점을 얻을 수 있다는 것입니다.
예를 들어, 위의 쿼리에서 명령문을 한 번 준비한 다음 여러 데이터에서 데이터 배열을 만드는 과정을 반복하고-> 실행을 필요한만큼 반복 할 수 있습니다.
답변
명령 텍스트는 다음과 같아야합니다.
cmdText = "SELECT foo FROM bar WHERE baz = ?"
cmdText = "EXEC foo_from_baz ?"
그런 다음 매개 변수 값을 추가하십시오. 이렇게하면 con 값이 값으로 만 사용되는 반면 다른 방법에서는 변수 fuz가 다음으로 설정됩니다.
"x'; delete from foo where 'a' = 'a"
무슨 일이 일어날 지 알 수 있습니까?
답변
다음은 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 / Express
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