准备好的语句如何帮助我们防止SQL注入攻击?

维基百科说:

预处理语句对SQL注入具有弹性,因为 参数值,稍后使用不同的 协议,不需要正确转义。如果原始语句 模板不能从外部输入派生,SQL注入不能 发生。

我不太明白其中的原因。如何用简单的英语和一些例子来简单地解释?


当前回答

ResultSet rs = statement.executeQuery("select * from foo where value = " + httpRequest.getParameter("filter");

让我们假设在Servlet中有这个。如果一个恶意的人传递了一个坏的值为'过滤器',你可能会黑你的数据库。

其他回答

我把答案通读了一遍,仍然觉得有必要强调阐明事先陈述的本质的关键点。考虑两种查询数据库的方法,其中涉及用户输入:

天真的方法

其中一个将用户输入与部分SQL字符串连接起来以生成SQL语句。在这种情况下,用户可以嵌入恶意SQL命令,然后将这些命令发送到数据库执行。

String SQLString = "SELECT * FROM CUSTOMERS WHERE NAME='"+userInput+"'"

例如,恶意用户输入可能导致SQLString等于"SELECT * FROM CUSTOMERS WHERE NAME='James';DROP TABLE CUSTOMERS;' "

由于恶意用户的存在,SQLString包含2条语句,其中第二条语句(“DROP TABLE CUSTOMERS”)将造成损害。

准备好的语句

在这种情况下,由于查询和数据分离,用户输入永远不会被视为SQL语句,因此永远不会被执行。正是由于这个原因,注入的任何恶意SQL代码都不会造成损害。所以“DROP TABLE CUSTOMERS”在上面的例子中永远不会被执行。

简而言之,通过用户输入引入的恶意代码将不会被执行!

关键短语是不需要正确转义。这意味着你不需要担心人们试图插入破折号、撇号、引号等等……

一切都为你安排好了。

当您创建准备好的语句并将其发送到DBMS时,它将存储为SQL查询以供执行。

稍后将数据绑定到查询,以便DBMS使用该数据作为执行(参数化)的查询参数。DBMS不会使用你绑定的数据作为已经编译的SQL查询的补充;只是数据而已。

这意味着使用准备好的语句执行SQL注入从根本上是不可能的。预处理语句的本质及其与DBMS的关系阻止了这一点。

简单的例子:

  "select * from myTable where name = " + condition;

如果用户输入是:

  '123'; delete from myTable; commit;

查询将像这样执行:

  select * from myTable where name = '123'; delete from myTable; commit;

基本上,通过准备好的语句,来自潜在黑客的数据被视为数据——它不可能与应用程序SQL混合和/或被解释为SQL(当传入的数据直接放入应用程序SQL时可能发生)。

这是因为预处理语句首先“准备”SQL查询,以找到一个有效的查询计划,然后发送可能来自表单的实际值——在查询实际执行的时候。

更多信息请点击这里:

准备好的语句和SQL注入