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

sql*_*ild 52 .net c# sql sql-server-2005 parameterized-query

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

1.> -------------

SqlCommand cmd = new SqlCommand("INSERT INTO dbo.Cars " +"VALUES(@TagNbr);" , conn);
cmd.Parameters.Add("@TagNbr", SqlDbType.Int);
cmd.Parameters["@TagNbr"].Value = txtTagNumber.Text;
Run Code Online (Sandbox Code Playgroud)

2.> --------------

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

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

OJ.*_*OJ. 45

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

  • @sqlchild:对不起,误会了.它只会在相应的列/字段中插入字符串"DROP table Cars". (4认同)
  • @sqlchild:您开始更改主题并且已经接受了原始问题的答案.请考虑发布有关您需要了解的其他事项的其他/新问题.这就是SO应该如何工作,并允许更好的发现并使每个人受益. (3认同)
  • @Christian.K:先生,我的意思是,如果我将文本框中的DROP表汽车传递给插入语句,请插入汽车值(@carname); cmd.Parameters.Add(@ carname,SQLDBTYPE varchar),然后参数化查询会做什么? (2认同)
  • @sqlchild:不,它不被称为转义.它是数据库提供的一种机制,可以避免不必要的转义.我认为你需要阅读更多关于SQL注入的背景知识(例如http://en.wikipedia.org/wiki/SQL_injection) - 不仅适用于评论或对原始问题的回复. (2认同)

Mul*_*lki 16

当一个可能的参数在其中包含sql且字符串未按原样处理时,就会发生sql注入

例如:

var sqlquerywithoutcommand = "select * from mytable where rowname =  '" + condition+''";
Run Code Online (Sandbox Code Playgroud)

并且条件是来自请求中的用户的字符串.如果条件是恶意的,例如:

var sqlquerywithoutcommand = "select * from mytable where rowname =  '" + "a' ;drop table  mytable where '1=1"+"'";
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

select * from mytable where rowname = 'a'';drop table mytable where 1=1'''
Run Code Online (Sandbox Code Playgroud)

在essense中,它将使用rowname = a'; drop table mytable,其中1 = 1'并且不运行剩余的脚本

  • 但是当 sql 从参数中获取值时,它是如何读取它的,我的意思是它会以与直接从字符串相同的方式获取它,即将它读取为 drop table mytable ,还是我错了? (2认同)

小智 13

想象一下动态SQL查询

sqlQuery='SELECT * FROM custTable WHERE User=' + Username + ' AND
Pass=' + password
Run Code Online (Sandbox Code Playgroud)

所以一个简单的SQL注入只是将Username放入,因为' OR 1=1--这将有效地使sql查询:

sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS='
+ password
Run Code Online (Sandbox Code Playgroud)

这表示选择所有客户,他们的用户名是空白('')或1 = 1,这是一个布尔值,等于true.然后它使用 - 注释掉查询的其余部分.因此,这将打印出所有客户表,或者随意使用它,如果登录,它将以第一个用户的权限登录,这通常是管理员.

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

sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?'
Run Code Online (Sandbox Code Playgroud)

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

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

现在,在这一点上,你可能会想,这根本不会改变任何东西.当然你仍然可以在用户名字段中输入类似Nobody OR 1 = 1'的内容,从而有效地进行查询:

sqlQuery='SELECT * FROM custTable WHERE User=Nobody OR 1=1'-- AND
Pass=?'
Run Code Online (Sandbox Code Playgroud)

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

参数化查询的工作方式是,sqlQuery作为查询发送,数据库确切知道此查询将执行的操作,然后才会将用户名和密码仅作为值插入.这意味着它们不能影响查询,因为数据库已经知道查询将执行什么操作.所以在这种情况下,它会查找用户名"Nobody OR 1=1'--"和空密码,这应该是错误的.

取自


Cad*_*oux 5

参数化查询可以处理一切 - 为什么要这么麻烦呢?

通过参数化查询,除了一般注入之外,您还可以获得处理的所有数据类型、数字(int 和 float)、字符串(带有嵌入的引号)、日期和时间(当不调用 .ToString() 时,不会出现格式问题或本地化问题由于文化不变,您的客户转移到具有意外日期格式的机器)。