参数和SQL注入asp.net

时间:2016-05-13 02:23:27

标签: c# asp.net sql-injection

我在whereclause中使用了参数,但是这个{0}的变量呢。我是否需要为它创建一个参数来阻止sql注入?

("...inner join db1.dbo.table1.id on db2.dbo.table2.id = {0}.dbo.table3.id where name=@name",abc)

var abc = ddl2.SelectedItem.Text;

cmd.Parameters.AddWithValue("@name", ddl1.selectedvalue);

4 个答案:

答案 0 :(得分:3)

据我所知,您实际上不能“对数据库名称/表名称进行'参数化”。

在这种情况下,String.Format不解决SQL注入,因为用户可以将ddl2.SelectedItem.Text更改为他们想要的任何内容。

如果您需要数据库名称的动态值,我建议您将该值保留为const或将其存储在您完全控制/从未发送或解释客户端的位置。

答案 1 :(得分:0)

我建议您使用任何ORM(对象关系映射),即实体框架或n-hibernate等,并使用linq编写查询,这将阻止您从SQL注入应用程序。

答案 2 :(得分:0)

不幸的是,正如Abbath已经提到的,这种类型的构造不可参数化。正如阿巴斯所提到的,最好的解决方案是将这些论点置于你的绝对控制之下,但有时候需要这样的结构,并且可能无法完全控制它们。

对于这种情况,在这种情况下,最好的建议是逃避争论。在这种情况下,示例代码上由{0}表示的数据库名称。 有两种可能的机制来实现这一目标:

a)创建一种允许您参数化查询的机制

优点:您可以从任何驱动程序(.Net,ODBC等)重用相同的解决方案

缺点:多一点工作。在这种情况下,您将不再使用select。

例如(我包含一个内部联接的简单示例,就像您的代码一样):

CREATE PROC sp_MyQuery( @target_db_name sysname, @name nvarchar(100))
AS
BEGIN
    DECLARE @cmd nvarchar(max)
    DECLARE @parameters nvarchar(max)
    SELECT @cmd = N'SELECT * FROM msdb.sys.objects inner join ' 
        + quotename(@target_db_name) + N'.sys.sql_modules 
        on msdb.sys.objects.object_id = ' 
        + quotename(@target_db_name) + N'.sys.sql_modules.object_id WHERE name = @name'
     print @cmd -- See the command before it is executed.
    set @parameters = N'@name nvarchar(100)'
    EXEC sp_executesql @cmd, @parameters, @name = @name
END
go

-- Example of usage
DECLARE @target_db_name sysname = 'msdb'
DECLARE @name nvarchar(100) = 'sp_help_operator'
EXEC sp_MyQuery @target_db_name, @name 
go

此时,您可以像平常一样使用SqlParameter个对象。例如:

sqlcmd.CommandText = @"[dbo].[sp_MyQuery]";
sqlcmd.CommandType = System.Data.CommandType.StoredProcedure;
sqlcmd.Parameters.AddWithValue("@target_db_name", ddl0.selectedvalue);
sqlcmd.Parameters.AddWithValue("@name", ddl1.selectedvalue);
SqlDataReader reader = sqlcmd.ExecuteReader();

b)转义CLR代码中的DB名称

优势:更容易实施

缺点:特定于应用程序的解决方案,您需要注意潜在的Unicode-DB整理翻译问题。

例如(与上述相同的查询):

sqlcmd.CommandText = String.Format(@"
    SELECT * FROM msdb.sys.objects inner join [{0}].sys.sql_modules on msdb.sys.objects.object_id = [{0}].sys.sql_modules.object_id WHERE name = @name;",
    ddl0.selectedvalue.Replace("]", "]]"));
sqlcmd.CommandType = System.Data.CommandType.Text;
sqlcmd.Parameters.AddWithValue("@name", ddl1.selectedvalue);
SqlDataReader reader2 = sqlcmd.ExecuteReader();

我通常建议尽可能使用解决方案(a),但这两种解决方案都可以帮助您防止SQL注入。

顺便说一句。以下链接也非常有用:https://blogs.msdn.microsoft.com/raulga/2007/01/04/dynamic-sql-sql-injection/

我希望信息有所帮助。

答案 3 :(得分:-2)

如果你像这样使用string.format

,你不需要为abbc创建参数
var abc = ddl2.SelectedItem.Text;
string.format("...inner join db1.dbo.table1.id on db2.dbo.table2.id = {0}.dbo.table3.id where name=@name",abc)
cmd.Parameters.AddWithValue("@name", ddl1.selectedvalue);