我是一名为内部用户撰写的桌面开发人员,因此我并不担心恶意黑客,但我想知道在更新将在服务器上执行sql的值时是否可以输入任何内容。
业务定义了他们的内容架构,我有一个CRUD应用程序,当架构发生变化时不必更改它们,因为验证细节是由表驱动的,而更新是使用动态SQL。我必须在他们的数据条目中支持单引号,所以当他们输入它们时,我会在服务器上执行SQL之前将它们加倍。然而,从我读过的内容来看,这不足以阻止注射。
所以我的问题是,他们可以在自由格式文本字段中输入哪些文本可以更改服务器上的内容而不是存储为文字值?
基本上,我在运行时构建一个遵循模式的SQL语句:
更新表set field = value其中pkField = pkVal
使用这个VB.NET代码:
Friend Function updateVal(ByVal newVal As String) As Integer
Dim params As Collection
Dim SQL As String
Dim ret As Integer
SQL = _updateSQL(newVal)
params = New Collection
params.Add(SQLClientAccess.instance.sqlParam("@SQL", DbType.String, 0, SQL))
Try
ret = SQLClientAccess.instance.execSP("usp_execSQL", params)
Catch ex As Exception
Throw New Exception(ex.Message)
End Try
Return ret
End Function
Private Function _updateSQL(ByVal newVal As String) As String
Dim SQL As String
Dim useDelimiter As Boolean = (_formatType = DisplaySet.formatTypes.text)
Dim position As Integer = InStr(newVal, "'")
Do Until position = 0
newVal = Left(newVal, position) + Mid(newVal, position) ' double embedded single quotes '
position = InStr(position + 2, newVal, "'")
Loop
If _formatType = DisplaySet.formatTypes.memo Then
SQL = "declare @ptrval binary(16)"
SQL = SQL & " select @ptrval = textptr(" & _fieldName & ")"
SQL = SQL & " from " & _updateTableName & _PKWhereClauses
SQL = SQL & " updatetext " & _updateTableName & "." & _fieldName & " @ptrval 0 null '" & newVal & "'"
Else
SQL = "Update " & _updateTableName & " set " & _fieldName & " = "
If useDelimiter Then
SQL = SQL & "'"
End If
SQL = SQL & newVal
If useDelimiter Then
SQL = SQL & "'"
End If
SQL = SQL & _PKWhereClauses
End If
Return SQL
End Function
当我将文本字段更新为值
时雷德蒙'; drop table OrdersTable -
它生成:
Update caseFile set notes = 'Redmond''; drop table OrdersTable--' where guardianshipID = '001168-3'
并将值更新为他们输入的文字值。
他们还可以输入什么来注入SQL?
同样,我并不担心有人想在他们的工作中破解服务器,但是想知道如果他们不小心粘贴来自其他地方的文本并打破了某些东西。
感谢。
答案 0 :(得分:2)
无论您如何清理用户输入,增加攻击面都是您正在做的事情的真正问题。如果你回顾一下SQL注入的历史,你会发现随着时间的推移,新的,甚至更具创造性的通过它们造成破坏的方法已经出现。虽然你可能已经避免了已知的事情,但总是潜伏着,这使得这类代码难以生产。你最好简单地使用不同的方法。
答案 1 :(得分:2)
您还可以评估替代解决方案。使用参数动态生成SQL。像这样:
// snippet just for get the idea
var parameters = new Dictionary<string, object>();
GetParametersFromUI(parameters);
if (parameters.ContainsKey("@id")) {
whereBuilder.Append(" AND id = @id");
cmd.Parameters.AddWithValue("@id", parameters["@id"]);
}
...
答案 2 :(得分:1)
假设你逃避字符串文字(根据你所说的那样做),你应该是安全的。我能想到的唯一另一件事是,如果你使用基于unicode的字符集与数据库通信,请确保你发送的字符串在该编码中有效。
答案 3 :(得分:1)
与你的加倍代码一样丑陋(:p - 尝试String.Replace。)我很确定能做到这一点。
答案 4 :(得分:1)
唯一的安全假设是,如果您没有使用参数化查询(并且您不是,仅此处,因为您将输入字符串连接到您的sql中),那么您“不安全。
答案 5 :(得分:1)
您永远不会永远不想使用将直接执行的用户输入来构建SQL语句。正如您所发现的那样,这会导致SQL注入攻击。正如您所描述的那样,某人在您的数据库中删除表格将是微不足道的。
您希望使用参数化查询,使用占位符为值构建SQL字符串,然后为这些参数传递值。
使用VB你会做类似的事情:
'Define our sql query'
Dim sSQL As String = "SELECT FirstName, LastName, Title " & _
"FROM Employees " & _
"WHERE ((EmployeeID > ? AND HireDate > ?) AND Country = ?)"
'Populate Command Object'
Dim oCmd As New OledbCommand(sSQL, oCnn)
'Add up the parameter, associated it with its value'
oCmd.Parameters.Add("EmployeeID", sEmpId)
oCmd.Parameters.Add("HireDate", sHireDate)
oCmd.Parameters.Add("Country", sCountry)
(取自here的例子)(也不是我不是VB程序员所以这可能不是正确的语法,但它得到了重点)