Vb.net 我的用户可以注入我的动态sql吗?

Vb.net 我的用户可以注入我的动态sql吗?,vb.net,sql-server-2005,Vb.net,Sql Server 2005,我是一名为内部用户编写的桌面开发人员,因此我不担心恶意黑客,但我想知道他们在更新将在服务器上执行sql的值时是否可以输入任何内容 业务定义了他们的内容模式,我为他们提供了一个CRUD应用程序,当他们的模式更改时,不必更改该应用程序,因为验证细节是表驱动的,更新是使用动态SQL进行的。我必须在它们的数据输入中支持单引号,所以当它们输入单引号时,我会在服务器上执行SQL之前将它们加倍。然而,据我所知,这不足以阻止注射 所以我的问题是,他们可以在一个自由格式的文本字段中输入什么文本来改变服务器上的某些

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

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

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

基本上,我在运行时按照以下模式构建SQL语句:

更新表集合字段=值,其中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
当我将文本字段更新为值时

雷德蒙;删除表OrdersTable--

它产生:

Update caseFile set notes = 'Redmond''; drop table OrdersTable--' where guardianshipID = '001168-3'
并将值更新为输入的文字值

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


再说一次,我并不担心有人想在他们的工作中入侵服务器,但我想知道他们是否会意外地从其他地方粘贴文本并破坏某些东西


谢谢。

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

与您的加倍代码一样难看(:p-请尝试)我很确定这会起到作用。

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

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

您永远不希望使用用户输入构建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)

(示例摘自)(也不是我不是VB程序员,所以这可能不是正确的语法,但它能让人理解)

您还可以评估其他解决方案。使用参数动态生成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"]);
}
...
//这段代码只是为了让你明白
var参数=新字典();
GetParametersFromUI(参数);
if(parameters.ContainsKey(“@id”)){
其中builder.Append(“AND id=@id”);
cmd.Parameters.AddWithValue(“@id”,Parameters[“@id”]);
}
...

“我不担心有人想在他们的工作岗位上入侵服务器”-你最好是这样,不满的员工会成为非常恶劣的攻击者。如果你是其中一员,你会使用什么sql?+1作为一个好问题。这是我一直想知道的。我在教科书中看到很多模糊的断言,认为这是不够的,但从未解释过原因。如果有人能用一个明确的用户输入示例来正确回答这个问题,我会很高兴。我现在敢打赌,这不会发生,而且完全没有回答建议使用参数化SQL的非常具体问题的答案将被投票到顶部。对于VB.NET来说,将单引号更改为双引号可能没什么问题,但当Beth使用另一种语言时,这可能无法正常工作。最好养成使用参数化SQL编写正确的防注入代码的习惯,而不是编写特定于语言的输入清理代码。只需要忘记逃出一次,你的桌子就掉了。Beth想知道是否还有其他输入可以用来入侵她的数据库。对于参数化SQL,她不必感到奇怪。@CanSpice-我理解你的观点,但在某些情况下,通过字符串连接的动态SQL是不可避免的。并非SQL中的所有内容都可以参数化。在这些情况下,我们必须理解为什么有些东西不安全,这样我们才能理解并减轻风险。这并不能回答问题。这就是为什么它不安全?你能演示一下吗?好的,那么他们会输入哪些会影响服务器的文本呢?请参阅理论案例。我没有说你没有受到保护,我只是说,唯一安全的假设是,只有当你对来自用户的所有数据使用参数化查询时,你才安全。@Mark,谢谢你的链接。我知道我不是第一个问的人,但是找不到相关的帖子。@Mark-Good链接。但是,缓冲区截断在这里不适用。MySQL反斜杠不适用。Unicode是非常有趣的。我已经在SQL Server上进行了测试,它确实会将‘’字符转换为常规撇号。这依赖于转换为char/varchar(与Unicode相反),虽然这在执行常规查询时不会发生。我理解,对于一个向世界开放更新的web应用程序,这是有意义的,但我的用户