参数化查询如何帮助SQL注入?

时间:2011-03-29 05:50:33

标签: c# .net sql sql-server-2005 parameterized-query

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

  1. txtTagNumber作为查询参数传递

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

    int tagnumber = txtTagNumber.Text.ToInt16(); /* EDITED */
    INSERT into Cars values(tagnumber.Text); /* then is it the same? */
    
  3. 此外,在这里,我将使用正则表达式验证来停止插入非法字符。

6 个答案:

答案 0 :(得分:43)

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

答案 1 :(得分:16)

当一个可能的参数中包含sql且没有处理字符串时,会发生sql注入

例如:

var sqlquerywithoutcommand = "select * from mytable where rowname =  '" + condition+''";

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

var sqlquerywithoutcommand = "select * from mytable where rowname =  '" + "a' ;drop table  mytable where '1=1"+"'";

你最终可能会运行恶意脚本。

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

无论发生什么,都可以确保无法运行注入脚本。

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

select * from mytable where rowname = 'a'';drop table mytable where 1=1'''

在essense中它将寻找一行rowname = a'; drop table mytable where 1 = 1' 而不是运行剩余的脚本

答案 2 :(得分:9)

  

想象一下动态SQL查询

sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND
Pass=' + password
     

所以一个简单的sql注入只是将Username放入' OR 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=?'
     

parameters.add(" User",username)parameters.add(" Pass",password)

     

其中用户名和密码是指向关联的变量   输入的用户名和密码

     

现在,你可能在想,这并没有改变任何事情   一点都不当然你仍然可以放入用户名字段   类似于Nobody OR 1 = 1' - ,有效地进行查询:

sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND
Pass=?'
     

这似乎是一个有效的论点。但是,你错了。

     

参数化查询的工作方式是sqlQuery作为一个发送   查询,数据库确切知道此查询将执行的操作,以及   只有这样它才会将用户名和密码作为值插入。   这意味着它们不能影响查询,因为数据库已经存在   知道查询会做什么。所以在这种情况下,它会寻找一个   "Nobody OR 1=1'--"的用户名和空白密码   虚假。

Taken from

答案 3 :(得分:1)

参数化查询处理所有事情 - 为什么要麻烦?

使用参数化查询,除了常规注入外,还可以获得所有处理的数据类型,数字(int和float),字符串(带嵌入引号),日期和时间(无。格式问题或本地化问题.ToString()没有使用不变文化调用,并且您的客户端移动到具有意外日期格式的计算机上。)

答案 4 :(得分:1)

参数化查询允许客户端从查询文本中单独传递数据。 在大多数免费文本的地方你会做验证+逃避。 当然,参数化对其他类型的注入没有帮助,但由于参数是单独传递的,因此它们不能用作执行文本查询。

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

答案 5 :(得分:1)

为什么会有这样的感觉是完全可以理解的。

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

VS

sqlQuery = "select * from users where username=@username;"

上述两个查询似乎都做了同样的事情。但实际上他们并没有。

前者使用输入来查询,后者决定查询,但只在查询执行期间替换输入。

更清楚,参数'值位于堆栈中的某些位置,其中变量'存储器存储并在需要时用于搜索。

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

在同一输入上,后者会在' OR '1'='表的username字段中搜索users,并在查询字符串中使用静态指定查询sqlQuery

只是为了巩固它,这就是你使用参数进行查询的方式:

SqlCommand command = new SqlCommand(sqlQuery,yourSqlConnection);

SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "@username";
parameter.Value = "xyz";

command.Parameters.Add(parameter);