关于vb.net:Can我的用户注入我的动态sql?

Can my users inject my dynamic sql?

我是为内部用户编写的桌面开发人员,所以我不担心恶意黑客,但我想知道他们在更新将在服务器上执行SQL的值时是否可以输入任何内容。

业务定义了它们的内容架构,我为它们提供了一个CRUD应用程序,当它们的架构更改时,不必更改该应用程序,因为验证详细信息是表驱动的,更新是使用动态SQL的。我必须在它们的数据输入中支持单引号,所以当它们输入时,我会在服务器上执行SQL之前将它们加倍。然而,根据我读到的,这不足以停止注射。

所以我的问题是,他们可以在一个自由格式的文本字段中输入什么文本,这个字段可以更改服务器上的某些内容,而不是存储为文本值?

基本上,我在运行时构建的SQL语句遵循以下模式:

更新表集字段=值,其中pkfield=pkval

使用此vb.net代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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

当我将文本字段更新为值时

Redmond'; drop table OrdersTable--

它产生:

1
Update caseFile set notes = 'Redmond''; drop table OrdersTable--' where guardianshipID = '001168-3'

并将值更新为输入的文字值。

他们还可以输入什么来注入SQL?

再说一次,我不担心有人想在他们的工作中攻击服务器,但我想知道如果他们不小心从其他地方粘贴了文本并破坏了一些东西。

谢谢。


您还可以评估其他解决方案。使用参数动态生成SQL。像这样:

1
2
3
4
5
6
7
8
9
10
// 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"]);
}
...


无论您如何清理用户输入,增加攻击面都是您所做工作的真正问题。如果回顾一下SQL注入的历史,您会发现,随着时间的推移,新的、甚至更具创造性的方法已经出现了,它们会造成巨大的破坏。虽然您可能已经避免了已知的代码,但它总是潜伏在转角处,这使得这种类型的代码很难产生。你最好使用不同的方法。


您永远不会希望使用将直接执行的用户输入来构建SQL语句。正如您所发现的,这会导致SQL注入攻击。正如您所描述的,对于某人来说,在您的数据库中删除一个表是很简单的。

您希望使用参数化查询,其中使用值的占位符构建SQL字符串,然后将这些参数的值传入。

使用vb,你可以做如下的事情:

1
2
3
4
5
6
7
8
9
10
11
12
'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)

(这里举的例子)(我也不是一个VB程序员,所以这可能不是正确的语法,但它得到了重点)


唯一安全的假设是,如果您不使用参数化查询(并且您不完全使用这里的查询,因为您要将输入字符串连接到SQL中),那么您就不安全。


和加倍代码一样难看(:p-try-string.replace),我很肯定这能解决问题。


假设您转义字符串文本(从您所说的操作中),那么您应该是安全的。我唯一能想到的是,如果使用基于Unicode的字符集与数据库通信,请确保发送的字符串在该编码中有效。