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

发布于 2024-10-26 23:07:41 字数 536 浏览 6 评论 0原文

在查询 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(); /* 编辑 */
    插入汽车值(tagnumber.Text); /* 那么是一样的吗? */
    

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

In both queries 1 and 2, the text from the textbox is inserted into the database. What's the significance of the parameterized query here?

  1. Passing txtTagNumber as a query parameter

    SqlCommand cmd = new SqlCommand("INSERT INTO dbo.Cars " +"VALUES(@TagNbr);" , conn);
    cmd.Parameters.Add("@TagNbr", SqlDbType.Int);
    cmd.Parameters["@TagNbr"].Value = txtTagNumber.Text;
    
  2. Converting txtTagNumber to an integer before constructing the query

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

Also, here I would use Regular Expression validation to stop insertion of illegal characters.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

千纸鹤 2024-11-02 23:07:41

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

Parameterized queries do proper substitution of arguments prior to running the SQL query. It completely removes the possibility of "dirty" input changing the meaning of your query. That is, if the input contains SQL, it can't become part of what is executed because the SQL is never injected into the resulting statement.

聆听风音 2024-11-02 23:07:41

想象一个动态 SQL 查询

sqlQuery='SELECT * FROM custTable WHERE User=' + 用户名 + ' AND
密码='+密码

因此,一个简单的 SQL 注入只需将用户名作为 ' 或
1=1--
这将有效地进行sql查询:

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

这表示选择用户名为空 ('') 或的所有客户
1=1,这是一个布尔值,相当于 true。然后用--来注释
查询的其余部分。所以这只会打印出所有
客户表,或者用它做任何你想做的事情,如果登录的话,它
将使用第一个用户的权限登录,这通常可以是
管理员。

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

sqlQuery='SELECT * FROM custTable WHERE User=?并通过=?'

parameters.add("用户", 用户名)parameters.add("密码", 密码)

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

现在,您可能会想,这不会改变任何事情
根本不。当然,您仍然可以直接输入用户名字段
像Nobody OR 1=1'--这样的东西,有效地进行查询:

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

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

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


来源:lavamunky.com; 2011 年 11 月

Imagine a dynamic SQL query

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

so a simple sql injection would be just to put the Username in as ' OR
1=1--
This would effectively make the sql query:

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

This says select all customers where they're username is blank ('') or
1=1, which is a boolean, equating to true. Then it uses -- to comment
out the rest of the query. So this will just print out all the
customer table, or do whatever you want with it, if logging in, it
will log in with the first user's privileges, which can often be the
administrator.

Now parameterized queries do it differently, with code like:

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

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

where username and password are variables pointing to the associated
inputted username and password

Now at this point, you may be thinking, this doesn't change anything
at all. Surely you could still just put into the username field
something like Nobody OR 1=1'--, effectively making the query:

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

And this would seem like a valid argument. But, you would be wrong.

The way parameterized queries work, is that the sqlQuery is sent as a
query, and the database knows exactly what this query will do, and
only then will it insert the username and passwords merely as values.
This means they cannot effect the query, because the database already
knows what the query will do. So in this case it would look for a
username of "Nobody OR 1=1'--" and a blank password, which should come
up false.

Source: lavamunky.com; Nov 2011

猫弦 2024-11-02 23:07:41

当可能的参数中包含 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'''

本质上它将查找 rowname = a';drop table mytable where 1=1' 的行
并且不运行剩余的脚本。

SQL injection happens when a possible parameter has SQL within it and the strings are not handled as it should be

eg:

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

and the condition is a string coming from the user in the request. If condition is malicious
say eg:

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

you could end up running malicious scripts.

However, using parameters the input will be cleaned of any characters which might escape string characters, which means you can be ensured no matter what comes in it will not be able to run inject scripts.

Using the command object with parameters the SQL actually executed would look like this:

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

in essence it will be looking for a row with rowname = a';drop table mytable where 1=1'
and not running the remaining script.

圈圈圆圆圈圈 2024-11-02 23:07:41

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

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

Parameterized queries handles everything - why go to the trouble?

With parametrized queries, in addition to general injection, you get all the data types handled, numbers (int and float), strings (with embedded quotes), dates and times (no formatting problems or localization issues when .ToString() is not called with the invariant culture and your client moves to a machine with and unexpected date format).

违心° 2024-11-02 23:07:41

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

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

Parameterized queries allow the client to pass the data separately form the query text.
Where on most free from text you would do validation + escaping.
Of course Parameterization don't help against other kind of injection, but as the parameter are passed separately, they are not use as execution text query.

A good analogy would be the "recent" execution bit used with most of the modern processor and Operating system to protect from buffer overflow. It still allows the buffer overflow but prevent the execution of the injected data.

熊抱啵儿 2024-11-02 23:07:41

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

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

vs

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

上面的两个查询似乎做了同样的事情,但实际上却没有。

前者使用输入进行查询,后者决定查询,但仅替换查询执行期间的输入。

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

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

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

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

SqlCommand command = new SqlCommand(sqlQuery,yourSqlConnection);

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

command.Parameters.Add(parameter);

It is quite understandable why one would feel so.

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

vs

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

Both the above queries seem to do the same thing.But they actually don't.

The former uses input to for a query, the latter decides on the query but only substitutes the inputs as it is during the execution of the query.

To be more clear, the parameters' values are located some where on the stack where the variables' memory is stored and is used for search when needed.

So if we were to give ' OR '1'='1 as the input in username, the former would dynamically construct a new queries or queries as part of the sql query string sqlQuery which is then executed.

While on the same input, latter would search for ' OR '1'=' in the username field of the users table with the statically specified query in the query string sqlQuery

Just to consolidate it, this is how you use parameters to make query:

SqlCommand command = new SqlCommand(sqlQuery,yourSqlConnection);

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

command.Parameters.Add(parameter);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文