防止在动态列名中进行SQL注入

问题描述 投票:3回答:3

我走不了了 在我的系统的一部分(使用Postgres)编写一些动态sql条件。

我的问题是如何用我现在使用的方法最好地避免SQL注入。

EDIT(推理)。在一些表中有许多列(一个增长(只)的数字,并在其他地方维护)。我需要一种方法,让用户决定他们要查询哪一个(预定义的)列(如果必要的话,还可以应用字符串函数)。对用户来说,查询本身太复杂了,他们无法自己编写,也无法访问db。有1000个用户有不同的需求,我需要保持尽可能的灵活性--我不应该重新审视代码,除非主查询需要改变--同时,也无法知道用户需要使用什么条件。

我有一些对象(通过web服务接收),可以为一些大型sql查询生成一个条件(生成方法如下--还不完善)。

这个 _FieldName 是用户可以编辑的(参数名是可以编辑的,但不需要),我担心它可能是一个攻击载体。我把双引号(见引标识符)在字段名周围,试图对字符串进行消毒,这样一来,它永远不可能是一个关键词。我也可以对照字段名的列表进行查询,但这很难及时维护。

遗憾的是用户必须输入条件条件,我相信一定还有更多的我可以添加到sanatize方法中吗? 还有引用列名就安全了吗?我有限的测试似乎认为是这样)。

一个建立的例子条件是 "AND upper(brandloaded.make) like 'O%' and upper(brandloaded.make) not like 'OTHBRAND'" ...

感谢任何帮助或建议。

Public Function GetCondition() As String
   Dim sb As New Text.StringBuilder

   'put quote around the table name in an attempt to prevent some sql injection
   'http://www.postgresql.org/docs/8.2/static/sql-syntax-lexical.html
   sb.AppendFormat(" {0} ""{1}"" ", _LogicOperator.ToString, _FieldName)

   Select Case _ConditionOperator
      Case ConditionOperatorOptions.Equals
          sb.Append(" = ")

      ...

   End Select

   sb.AppendFormat(" {0} ", Me.UniqueParameterName) 'for parameter

   Return Me.Sanitize(sb)

End Function

Private Function Sanitize(ByVal sb As Text.StringBuilder) As String

   'compare against a similar blacklist mentioned here: http://forums.asp.net/t/1254125.aspx

    sb.Replace(";", "")
    sb.Replace("'", "")
    sb.Replace("\", "")
    sb.Replace(Chr(8), "")

    Return sb.ToString

End Function

Public ReadOnly Property UniqueParameterName() As String
     Get
         Return String.Concat(":" _UniqueIdentifier)
     End Get
End Property
.net sql vb.net postgresql sql-injection
3个回答
6
投票

你可以从数据库中获取列名,然后比较检查用户输入的列名是否有效。


2
投票

SQL注入发生的原因是用户输入的数据是在动态查询中使用的,没有进行paramerterizing。 不幸的是,在你的情况下,用户输入的数据不能被paramertized,解决方案是不让用户输入这些数据。

一个可能的变通办法是使用一个可接受字符的白名单(不是BLACKlist)。 但实际上,你应该看看如何获得一个fieldNames的列表,并验证用户的输入(然后使用你的字符串版本,而不是来自用户的字符串)。

用户输入的数据总是值得怀疑的,如果可能的话应该避免使用。


0
投票

你可以做的一件事是继续创建你的动态查询,但把这样的东西作为前缀。

"IF EXISTS(SELECT * FROM sys.columns where object_id=OBJECT_ID('mytable') and name = @dynamicName)
    SELECT * FROM mytable WHERE [" + dynamicName + "] = 'Whatever your test is.'"

是的,它使查询有点贵, 但它是防止注入。

© www.soinside.com 2019 - 2024. All rights reserved.