6

如果不在我的系统的一部分(使用 Postgres)中编写一些动态 sql 条件,就无法逃脱。

我的问题是如何最好地避免使用我目前使用的方法进行 SQL 注入。

编辑(推理):许多表中有许多列(一个(仅)增长并在其他地方维护的数字)。我需要一种方法来允许用户决定他们想要查询哪个(预定义)列(并在必要时应用字符串函数)。查询本身对于用户来说太复杂了,无法自己编写,他们也无权访问数据库。有 1000 名用户有不同的要求,我需要尽可能保持灵活性——除非主查询需要更改,否则我不应该重新访问代码——此外,无法知道用户需要什么条件采用。

我有对象(通过 Web 服务接收)为一些大型 sql 查询生成条件(生成方法如下 - 它还不完美)。

_FieldName是用户可编辑的(参数名称是,但它不需要),我担心它可能是一个攻击媒介。我在字段名称周围加上双引号(请参阅带引号的标识符)以尝试清理字符串,这样它就永远不会成为关键字。我还可以根据字段列表查找字段名称,但很难及时维护。

不幸的是,用户必须输入条件标准,我确定必须有更多我可以添加到 sanatize 方法?并引用列名使其安全吗?(我有限的测试似乎是这样认为的)。

一个示例构建条件是“AND upper(brandloaded.make) like 'O%' and upper(brandloaded.make) not like 'OTHERBRAND'”...

任何帮助或建议表示赞赏。

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
4

3 回答 3

8

您可以从数据库中获取列名并进行比较以检查用户是否输入了有效的列名。

于 2012-06-08T17:13:22.723 回答
2

发生 SQL 注入是因为用户输入的数据用于动态查询,而没有对其进行参数化。不幸的是,在您的情况下,用户输入的数据无法参数化,解决方案是不让用户输入该数据。

一种可能的解决方法是使用可接受字符的白名单(不是黑名单)。但实际上,您应该了解获取字段名称列表并验证用户输入(然后使用您的字符串版本,而不是来自用户的字符串)。

用户输入的数据总是可疑的,应尽可能避免。

于 2012-06-09T04:36:49.783 回答
1

您可以做的一件事是继续创建您的动态查询,但将这样的内容作为前缀:

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

是的,它使查询更加昂贵,但它可以防止注入。

于 2020-04-29T14:52:44.660 回答