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

在查询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; 

2。> ————–

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

此外,在这里我会使用正则expression式validation来停止插入非法字符。

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

当一个可能的参数在其中有sql并且string没有按照它应该被处理时,sql注入发生

例如:

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

并且该条件是请求中来自用户的string。 如果条件是恶意的,例如:

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

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

但使用参数input将清除任何可能转义string字符…

你可以确保不pipe进来什么都不能运行注入脚本。

使用带有参数的命令对象,实际执行的sql看起来像这样

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

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

想象一下dynamicSQL查询

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

所以一个简单的SQL注入将只是把用户名作为' OR 1=1--这将有效地使SQL查询:

 sqlQuery='SELECT * FROM custTable WHERE User='' OR 1=1-- ' AND PASS=' + password 

这就是说select所有的用户名是空白的('')或1 = 1,这是一个布尔值,等于true。 然后它使用 – 注释掉其余的查询。 因此,这只会打印出所有的客户表,或者做任何你想做的事情,如果login,它将以第一个用户的权限login,这通常是pipe理员。

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

 sqlQuery='SELECT * FROM custTable WHERE User=? AND Pass=?' 

parameters.add(“用户”,用户名)parameters.add(“Pass”,密码)

其中用户名和密码是指向相关的input用户名和密码的variables

现在,在这一点上,你可能会想,这根本没有任何改变。 当然,你仍然可以只是把用户名字段像没有人或1 = 1' – 有效地进行查询:

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

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

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

取自

参数化的查询处理一切 – 为什么要麻烦?

使用参数化查询,除了通用注入之外,还可以处理所有的数据types,数字(int和float),string(带有embedded式引号),date和时间(没有格式化问题或当没有调用.ToString与不变的文化和你的客户移动到一台机器与意想不到的date格式)。

参数化查询允许客户从查询文本分别传递数据。 在大多数免费的文本你会做validation+转义。 当然参数化对于其他types的注入没有帮助,但是由于参数是分开传递的,所以它们不能用作执行文本查询。

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

为什么会这样呢,这是可以理解的。

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

VS

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

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

前者使用input来进行查询,后者在查询上做出决定,但只是在执行查询期间replaceinput。

更清楚的是,参数的值位于variables存储器所在栈的某处,并在需要时用于search。

所以如果我们要给' OR '1'='1 sqlQuery ' OR '1'='1作为用户名的input,前者会dynamic地构造一个新的查询或查询作为sql查询stringsqlQuery一部分,然后执行。

而在相同的input时,后者将在查询stringsqlQuery中使用静态指定的查询在users表的username字段中search' OR '1'=' sqlQuery ' OR '1'='

只是为了巩固它,这是你如何使用参数进行查询:

 SqlCommand command = new SqlCommand(sqlQuery,yourSqlConnection); SqlParameter parameter = new SqlParameter(); parameter.ParameterName = "@username"; parameter.Value = "xyz"; command.Parameters.Add(parameter);