Sql server 动态SQL是否更容易受到SQL注入/黑客攻击?

Sql server 动态SQL是否更容易受到SQL注入/黑客攻击?,sql-server,Sql Server,动态SQL是否更容易受到SQL注入/黑客攻击? 如果是,如何防止?如果您使用参数而不是字符串连接来指定筛选条件,则它不应受到Sql注入的攻击 例如: 这样做: string sqlQuery = "SELECT * FROM Persons WHERE Persons.Name LIKE @name"; SqlCommand cmd = new SqlCommand ( sqlQuery ); ... cmd.Parameters.Add ("@name", SqlDbType.VarChar

动态SQL是否更容易受到SQL注入/黑客攻击?
如果是,如何防止?

如果您使用参数而不是字符串连接来指定筛选条件,则它不应受到Sql注入的攻击

例如:

这样做:

string sqlQuery = "SELECT * FROM Persons WHERE Persons.Name LIKE @name";

SqlCommand cmd = new SqlCommand ( sqlQuery );
...
cmd.Parameters.Add ("@name", SqlDbType.VarChar).Value = aName + "%";
与此相反:

   string sqlQuery = "SELECT * FROM Persons WHERE Persons.Name LIKE \'" + aName + "%\'";
第一个示例不易受sql注入攻击,但第二个示例非常容易受攻击

例如,在存储过程中使用的动态SQL也是如此。
在那里,您还可以创建一个使用参数的动态sql语句;然后,您应该使用允许您指定参数的
sp_executesql
执行动态语句。

如果您使用参数而不是字符串连接来指定筛选条件,则它不应受到Sql注入的攻击

例如:

这样做:

string sqlQuery = "SELECT * FROM Persons WHERE Persons.Name LIKE @name";

SqlCommand cmd = new SqlCommand ( sqlQuery );
...
cmd.Parameters.Add ("@name", SqlDbType.VarChar).Value = aName + "%";
与此相反:

   string sqlQuery = "SELECT * FROM Persons WHERE Persons.Name LIKE \'" + aName + "%\'";
第一个示例不易受sql注入攻击,但第二个示例非常容易受攻击

例如,在存储过程中使用的动态SQL也是如此。
在那里,您还可以创建一个使用参数的动态sql语句;然后,您应该使用
sp_executesql
执行动态语句,该语句允许您指定参数。

快速回答是肯定的,如果您在应用程序中动态构建Sql,您必须了解流氓将尝试的每一个小把戏。当您使用存储过程时,大部分存储过程将由您的供应商负责


减少sql注入机会的一个好方法是使用如上所述的参数查询,如果这不合适,请确保删除用户生成的任何字段中的非字母字符。去掉引号、分号等。如果您只查询数据,请确保您的连接只有足够的访问权限来执行它所需的操作,然后创建一个用户/安全组,无论该组只允许选择、不允许更新,尤其是不允许删除。将sql写入日志也是一种很好的做法,这样你就知道人们在做什么,你可以调整并发现注入尝试。

快速回答是肯定的,如果你在应用程序中动态构建sql,你必须知道流氓会尝试的每一个小把戏。当您使用存储过程时,大部分存储过程将由您的供应商负责


减少sql注入机会的一个好方法是使用如上所述的参数查询,如果这不合适,请确保删除用户生成的任何字段中的非字母字符。去掉引号、分号等。如果您只查询数据,请确保您的连接只有足够的访问权限来执行它所需的操作,然后创建一个用户/安全组,无论该组只允许选择、不允许更新,尤其是不允许删除。将sql写入日志也是一种很好的做法,这样您就知道人们在做什么,并且可以进行调优和发现注入尝试。

在TSQL内部,您应该使用
sp_ExecuteSql
来执行所需的任何动态命令(例如,提供灵活的搜索/排序)

请注意,除非您使用证书跳过某些限制,否则您仍然需要表的直接
SELECT
(etc)权限(与存储过程不同,存储过程隐式提供访问权限),但它应该是注入安全的。例如:

DECLARE @command nvarchar(4000), @name varchar(50)

SELECT @command = 'SELECT * FROM [CUSTOMER] WHERE [Name] = @Name',
       @name = 'Fred'

EXEC sp_ExecuteSql @command, N'@Name varchar(50)', @name
显然,在上面的内容中不需要使用动态SQL—这仅用于说明!当(存储过程中)有多个可选搜索条件或一个灵活的
ORDER BY
子句时,这是非常有用的

在非TSQL客户端中,可以对命令的参数执行相同的操作


还要注意的是,
sp_ExecuteSql
也使用了过程缓存,因此比原始的
EXEC(@command)

在TSQL内部,您应该使用
sp_ExecuteSql
来执行您需要的任何动态命令(例如,提供灵活的搜索/排序)

请注意,除非您使用证书跳过某些限制,否则您仍然需要表的直接
SELECT
(etc)权限(与存储过程不同,存储过程隐式提供访问权限),但它应该是注入安全的。例如:

DECLARE @command nvarchar(4000), @name varchar(50)

SELECT @command = 'SELECT * FROM [CUSTOMER] WHERE [Name] = @Name',
       @name = 'Fred'

EXEC sp_ExecuteSql @command, N'@Name varchar(50)', @name
显然,在上面的内容中不需要使用动态SQL—这仅用于说明!当(存储过程中)有多个可选搜索条件或一个灵活的
ORDER BY
子句时,这是非常有用的

在非TSQL客户端中,可以对命令的参数执行相同的操作


还要注意的是,
sp_ExecuteSql
还利用了过程缓存,因此比原始
EXEC(@command)
效率更高,这取决于查询的动态程度

如果您的意思是存储一个动态值,那么只要您按照Frederik的建议使用参数,这就不是问题

如果您的意思是根据动态条件构建查询,那么您可能会遇到麻烦:-)

例如,假设您有一个字段的字符串字典作为键更新,新值作为项更新。然后,您可以使用字典动态地构建更新查询。现在,如果一个黑客设法更改了你的一个字段名,他可能会设法插入一个自定义查询,从而入侵你的系统

为了避免这种情况,您可以对字段名进行一些巧妙的验证。也许可以对照表列检查它们。但更安全的选择是使用一个固定的查询来更新所有值,并为所有未更改的列提供原始值。通过这种方式,您可以对值使用参数,这是安全的,并且可以防止字段名中的sql注入


.

这取决于查询的动态性

如果您的意思是存储一个动态值,那么只要您按照Frederik的建议使用参数,这就不是问题

如果您的意思是根据动态条件构建查询,那么您可能处于tro中