Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 参数化查询如何帮助防止SQL注入?_C#_.net_Sql_Sql Server 2005_Parameterized Query - Fatal编程技术网

C# 参数化查询如何帮助防止SQL注入?

C# 参数化查询如何帮助防止SQL注入?,c#,.net,sql,sql-server-2005,parameterized-query,C#,.net,Sql,Sql Server 2005,Parameterized Query,在查询1和查询2中,文本框中的文本都被插入到数据库中。这里参数化查询的意义是什么 将txtTagNumber作为查询参数传递 SqlCommand cmd = new SqlCommand("INSERT INTO dbo.Cars " +"VALUES(@TagNbr);" , conn); cmd.Parameters.Add("@TagNbr", SqlDbType.Int); cmd.Parameters["@TagNbr"].Value = txtTagNumber.Text; 在

在查询1和查询2中,文本框中的文本都被插入到数据库中。这里参数化查询的意义是什么

  • txtTagNumber
    作为查询参数传递

    SqlCommand cmd = new SqlCommand("INSERT INTO dbo.Cars " +"VALUES(@TagNbr);" , conn);
    cmd.Parameters.Add("@TagNbr", SqlDbType.Int);
    cmd.Parameters["@TagNbr"].Value = txtTagNumber.Text;
    
  • 在构造查询之前将
    txtTagNumber
    转换为整数

    int tagnumber = txtTagNumber.Text.ToInt16(); /* EDITED */
    INSERT into Cars values(tagnumber.Text); /* then is it the same? */
    

  • 此外,这里我将使用正则表达式验证来停止插入非法字符。

    参数化查询在运行SQL查询之前对参数进行适当的替换。它完全消除了“脏”输入改变查询含义的可能性。也就是说,如果输入包含SQL,它就不能成为执行的内容的一部分,因为SQL从未被注入到结果语句中。

    参数化查询处理所有问题-为什么要麻烦呢


    使用参数化查询,除了常规注入外,您还可以处理所有数据类型、数字(int和float)、字符串(带嵌入引号)、日期和时间(如果未使用不变区域性调用.ToString(),并且您的客户端移动到具有意外日期格式的计算机,则不会出现格式问题或本地化问题).

    参数化查询允许客户端从查询文本中单独传递数据。 在最自由的文本上,您将执行验证+转义。 当然,参数化对其他类型的注入没有帮助,但由于参数是单独传递的,因此它们不能用作执行文本查询


    一个很好的类比是,大多数现代处理器和操作系统都使用“最近”执行位来防止缓冲区溢出。它仍然允许缓冲区溢出,但会阻止执行注入的数据。

    如果可能的参数中包含sql,并且字符串未按应有方式处理,则会发生sql注入

    例如:

    条件是来自请求中用户的字符串。如果条件是恶意的 比如说:

    您可能最终运行恶意脚本

    但是使用参数输入将清除可能转义字符串的任何字符

    您可以确保,无论输入什么,它都无法运行注入脚本

    使用带有参数的命令对象,实际执行的sql将如下所示

    select * from mytable where rowname = 'a'';drop table mytable where 1=1'''
    
    在本质上,它将查找rowname=a'的行;删除表mytable,其中1=1'
    不运行剩下的脚本是可以理解的

    sqlQuery = "select * from users where username='+username+';"
    
    vs

    上述两个查询似乎做了相同的事情,但实际上没有

    前者将输入用于查询,后者决定查询,但只替换查询执行期间的输入

    更清楚的是,参数值位于堆栈上存储变量内存的某些位置,并在需要时用于搜索

    因此,如果我们在用户名中输入
    '或'1'='1
    ,前者将动态地构造一个或多个新查询,作为sql查询字符串
    sqlQuery
    的一部分,然后执行

    在相同的输入上,后者将使用查询字符串
    sqlQuery

    为了整合它,以下是如何使用参数进行查询:

    SqlCommand command = new SqlCommand(sqlQuery,yourSqlConnection);
    
    SqlParameter parameter = new SqlParameter();
    parameter.ParameterName = "@username";
    parameter.Value = "xyz";
    
    command.Parameters.Add(parameter);
    
    想象一个动态SQL查询

    sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND
    Pass=' + password
    
    因此,一个简单的sql注入就是将用户名作为
    ”或
    1=1--
    这将有效地使sql查询:

    sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS='
    + password
    
    这表示选择用户名为空(“”)或 1=1,这是一个布尔值,等于true。然后它用--来评论 完成查询的其余部分。所以这会打印出所有的 客户表,或者对其执行任何您想要的操作,如果登录,则 将使用第一个用户的权限登录,这通常是 管理员

    现在,参数化查询的方式有所不同,代码如下:

    sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'
    
    参数。添加(“用户”,用户名)参数。添加(“通过”,密码)

    其中username和password是指向关联 输入用户名和密码

    现在,你可能会想,这不会改变任何事情 完全当然,您仍然可以输入用户名字段 类似于Nobody或1=1'--,有效地进行查询:

    sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND
    Pass=?'
    
    这似乎是一个有效的论点。但是,你错了

    参数化查询的工作方式是将sqlQuery作为 数据库确切地知道这个查询将做什么,并且 只有这样,它才会将用户名和密码仅仅作为值插入。 这意味着它们无法影响查询,因为数据库已经存在 知道查询将做什么。所以在这种情况下,它会寻找一个
    “无人或1=1”的用户名--“
    和一个空白密码,应该是 我错了


    既然参数化查询已经解决了问题,为什么还要编写自己的验证?另外,验证很难不使用文本输入,参数化查询会进行正确的“转义”(客户端实际上会将数据直接传递到服务器)。@dvhh:您能举个转义的例子吗?一个!无效的转义将是例如String.replace(“'”,“''”)。参数化执行命令使用另一种形式的编码,您几乎不需要知道可能的重复。它们肯定会处理SQL注入,但不会处理其他类型的注入(主要是web端注入,如javascript)。@sqlchild:表、列或过程名(通常是标识符)不能参数化,只能是“值”或者“论点”(正如OJ所说)。就像在WHERE或JOIN/in子句、函数或过程的参数中使用的一样,因此被称为“参数化”查询。@Christian.K:先生,我的意思是,如果我
    sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS='
    + password
    
    sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'
    
    sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND
    Pass=?'