在构建动态 SQL 时验证恶意 SQL 的参数

本文关键字:SQL 恶意 参数 验证 构建 动态 | 更新日期: 2023-09-27 18:33:19

我遇到必须使用动态SQL的情况,因为它看起来很难使用参数。

我将动态执行的查询如下所示。验证恶意 SQL @sql中的字符串的最佳方法是什么?我需要允许像"CountryId = 23"这样的有效字符串,但不允许像"从国家/地区删除"这样的字符串。我不希望一切都被禁止。

我正在使用 C# 对 SQL Server 2008 R2 运行此查询。

也许,我可以在SQL级别或C#级别进行验证,但我不确定哪个会更好。

SET @sql = 'SELECT * from Customers 
  where ' + @filterExpression + 
  ' order by ' + @sortExpression;
EXEC sp_executesql @sql

更新:Maxim的答案似乎是必须使用动态SQL的最佳选择,尽管应该尽可能避免像我在这篇文章中的代码那样的动态SQL。

我对 T-SQL 中的变量@filterExpression进行了一些验证,以验证恶意 SQL 代码,这些代码可能仍然会错过一些恶意情况,但这是我提出的 T-SQL。

IF PATINDEX('%DELETE %',  @filterExpression ) > 0 
  OR PATINDEX('%SELECT %FROM%',  @filterExpression ) > 0 
  OR PATINDEX('%;%',  @filterExpression ) > 0 
  OR PATINDEX('%DROP %',  @filterExpression ) > 0 
  OR PATINDEX('%CREATE %',  @filterExpression ) > 0 
  OR PATINDEX('%TRUNCATE %',  @filterExpression ) > 0 
  OR PATINDEX('%sys%',  @filterExpression ) > 0
  OR PATINDEX('%INDEX %', @filterExpression ) > 0
  OR PATINDEX('%UPDATE %', @filterExpression ) > 0
  OR PATINDEX('%INSERT %',  @filterExpression ) > 0
  OR PATINDEX('%EXEC %',  @filterExpression ) > 0
  OR PATINDEX('%EXECUTE %',  @filterExpression ) > 0
  OR PATINDEX('%CAST%',  @filterExpression ) > 0
  OR PATINDEX('%DECLARE %',  @filterExpression ) > 0
  OR PATINDEX('%CONVERT%',  @filterExpression ) > 0
BEGIN
  RETURN;
END

在构建动态 SQL 时验证恶意 SQL 的参数

  1. 您可以使用只读用户,这至少会阻止任何更新。
  2. 查找您看起来可疑的关键字:插入,更新等
  3. 使用这样的第三方库

这是一堆很好的抗注射技术。