代码之家  ›  专栏  ›  技术社区  ›  Beth

我的用户能注入我的动态sql吗?

  •  6
  • Beth  · 技术社区  · 14 年前

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

    业务定义了他们的内容模式,我为他们提供了一个CRUD应用程序,当他们的模式发生变化时,不必更改它,因为验证细节是表驱动的,更新是动态SQL。我必须在它们的数据输入中支持单引号,所以当它们输入单引号时,我会在服务器上执行SQL之前将它们加倍。然而,从我读到的情况来看,这不足以阻止注射。

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

    update table 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
    

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

    Redmond';删除表OrdersTable--

    它产生:

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

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

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

    6 回复  |  直到 14 年前
        1
  •  1
  •   Cᴏʀʏ bcherry    14 年前

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

        2
  •  2
  •   Keith Adler    14 年前

    不管你如何清理用户输入,增加攻击面才是你所做的真正的问题。如果您回顾一下SQL注入的历史,您会发现随着时间的推移,新的、甚至更具创造性的方法已经出现了。虽然您可能已经避免了已知的代码,但总是隐藏在角落里的东西使得这类代码难以生成。你最好用另一种方法。

        3
  •  2
  •   Jhonny D. Cano -Leftware-    14 年前

    // 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"]);
    }
    ...
    
        4
  •  1
  •   DaveShaw Thishin    14 年前

    就像你的代码一样难看(:p-Try) String.Replace 相反)我很肯定那会起作用的。

        5
  •  1
  •   Mark    14 年前

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

        6
  •  1
  •   abatishchev Karl Johan    14 年前

    您永远不希望使用用户输入构建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程序员,所以这可能不是正确的语法,但它明白了这一点)