当表名和where子句是变量时,防止SQL注入

时间:2015-06-20 02:25:59

标签: asp.net ado.net sql-injection

我有需要你的帮助。 目前,我使用ado.net构建了一个asp.net应用程序。我正在使用CommandText来构建动态查询,因此它具有SQL注入漏洞。 我的CommandText就像这样

String.Format("SELECT COUNT(*) FROM {0} {1}", tableName, whereClause)

TableName和whereClause由开发人员传入。如你所见,我不能在这里使用SQLParameters,因为我需要传递整个tableName和whereClause,而不仅仅是参数值。

我的防止SQL注入的解决方案是使用BlackList检查TableName和whereClause来查找恶意字符串,但我不知道这是在这种情况下最好的方法,不是吗。如果是这样,任何人都可以帮助我找到BlackList引用或库。

1 个答案:

答案 0 :(得分:2)

在不了解更多详细信息的情况下,您可以使用多种方法来避免SQL注入攻击或至少将可能造成的损害降至最低:

  1. 白名单比黑名单更安全:想想你是否真的需要访问除黑名单之外的所有表格。如果有人在以后添加表格,他或她可能会忘记将它们添加到后备列表中。
  2. 也许您可以限制对特定表格子集的访问。理想情况下,这些表遵循通用的命名方案,因此可以根据该方案验证表名。如果没有命名方案,您还可以添加可在程序或应用程序配置中访问的表的列表,以便检查表名是否包含在此列表中。如果将列表保存在配置文件中,则可以在不重新编译应用程序的情况下展开列表。
  3. 如果您不能将表名列入白名单,则至少可以通过查询sys.tables系统表来检查所提供的表名是否存在于数据库中(在SQL Server中,其他DBMS可能具有类似的表)。在此查询中,您可以使用参数以确保安全。
  4. 对于SQL Server,您应该将表名放在方括号(SELECT COUNT(*) FROM [" + tableName + "]")中。方括号用于分隔标识符(另请参阅此link)。为此,您必须检查tableName变量是否包含结束方括号。如果tableName变量可能包含模式标识符(例如dbo.MyTable,则必须首先拆分部分,然后添加方括号([dbo].[MyTable]),因为它们是单独的标识符(一个用于架构,一个用于表名称。)
  5. 使用正则表达式或类似检查非常仔细地验证变量的内容。对于表名来说这很容易,但WHERE子句很难,因为你基本上必须解析SQL WHERE子句并声明不包含危险代码。
  6. 最难的部分是检查WHERE子句。同样在这方面,如果您可以限制用户的选项并将可能的WHERE子句列入白名单,那将是最好的。这意味着用户可以根据用户输入从程序知道或构建的一系列WHERE子句中进行选择。这些已知的WHERE子句可以包含参数,因此可以安全地防止SQL注入攻击。如果您不能将WHERE子句列入白名单,则必须解析WHERE子句才能确定某个请求是否有危险。这需要付出很大的努力(如果你找不到可以为你做这个的库),那么我会尝试将尽可能多的动态查询部分列入白名单。
  7. 为了减少成功攻击的损害,您应该在权限非常有限的特定帐户下运行查询。您必须将另一个连接字符串添加到使用此帐户的配置文件,并使用有限的连接字符串创建连接。在SQL Server中,您可以移动此帐户可以访问特定架构的表,并限制对此帐户的此架构的访问权限。
  8. 保护您的服务免受未经授权的访问,以便只有受信任的开发人员才能访问它。您可以通过使用基础结构中的某些组件(防火墙,传输级安全性等)以及添加强大的用户身份验证机制来实现此目的。
  9. 将每个请求记录到服务中,以便识别用户和计算机。通知用户有关此日志记录机制的信息,以便他们知道如果出现任何问题,将会识别它们。
  10. 最后一点想法:即使为开发人员提供这样一种查询数据的开放方法似乎很容易,也要考虑是否真的有必要。一种可能的选择是不具有此开放访问权限,而是配置其他开发人员在配置文件中需要的查询。每个查询都获得一个标识符,查询文本存储在文件中,因此事先已知。您仍然可以在部署服务后添加新查询或更改现有查询。您可以在查询中允许调用者指定的参数(可能是编号参数方案,如p1,p2,...)。

    从上面的列表中可以看出,一旦允许这种开放访问,就很难(并且在某些方面几乎不可能)锁定服务并避免各种SQL注入攻击。使用上一段中描述的方法,您会失去一些灵活性,但您不必再担心SQL注入攻击了。