使用参数如何防止SQL注入?

时间:2018-08-08 16:20:05

标签: sql sql-injection

使用参数如何防止SQL注入?

许多人说使用参数代替输入字符串(例如,来自网站用户)可以防止SQL注入。

但是我不明白,我的意思是“ drop database”字符串和在查询中使用的“ drop database”字符串有什么不同?

3 个答案:

答案 0 :(得分:3)

SQL注入通过在RDBMS解析SQL语法之前修改SQL查询来起作用。

查询参数在解析完SQL后会发送到服务器 ,因此对于恶意值影响SQL语法的解析为时已晚。

查询参数只能解释为标量值,例如字符串。

答案 1 :(得分:3)

因为仅将“放置数据库”本身输入到字段中是不够的。您必须添加其他一些字符以说服SQL解释器终止上一条语句并开始一个新语句(以执行DROP)。除其他因素外,参数化将阻止此类序列通过SQL以预期的方式成功注入和解释。例如,'之类的字符可能会关闭字符串,因此将对其进行转义,以便将其视为变量的一部分,而不是SQL的一部分。

具体地说,http://bobby-tables.com/about包含一个有效的示例。在该示例中,有一些PHP代码可在表中插入一行:

$sql = "INSERT INTO Students (Name) VALUES ('" . $studentName . "');";
execute_sql($sql);

如果将$studentName设置为“ John”之类的正常值,则该代码产生的最终SQL字符串将是良性的:

INSERT INTO Students (Name) VALUES ('John');

同样,类似于您的示例,如果将$studentName设置为“ DROP TABLE Students”,它仍然没有任何作用。最终的SQL将是:

INSERT INTO Students (Name) VALUES ('DROP TABLE Students');

没有伤害。

但是...如果$studentName设置得更微妙,例如:

Robert'); DROP TABLE Students;--

最终的字符串如下:

INSERT INTO Students (Name) VALUES ('Robert'); DROP TABLE Students;--');

然后将其传递给SQL引擎,SQL引擎将其解释为两个语句(附带一个末尾的注释),并同时执行这两个语句,结果不愉快。

但是,如果$studentName中的值已作为参数传递而不是仅连接到标准字符串,则最终查询将以

结尾
INSERT INTO Students (Name) VALUES ('Robert\'); DROP TABLE Students;--'); 

请注意,转义的'位于中间,因此现在被视为字符串的一部分。它不再导致字符串在“ t”之后停止。

因此,在表的Name字段中输入的内容将是

Robert'); DROP TABLE Students;--

DROP TABLE语句将不会执行,因为SQL解释器永远不会看到它-它只是将其视为要添加到表中的值的一部分。

参数化意味着参数值中的任何内容都仅被视为字符串(或可能为数字)-它永远不能逃逸到该字符串之外,并且被视为SQL语句本身的一部分。

进一步阅读:

http://bobby-tables.com

How does the SQL injection from the "Bobby Tables" XKCD comic work?

可以帮助您更好地理解。

答案 2 :(得分:0)

请参阅有关sql注入攻击的示例:让我们假设这个伪代码:

myfunction(myuser)
{
    sql="SELECT user, password FROM users WHERE user='"+myuser+"'"
    return db.execute(sql)
}

通过此调用,攻击者将利用此漏洞获取表的所有密码:

myfunction("x' OR true OR 'a'='")

相反,如果程序员通过绑定变量执行查询:

myfunction(myuser)
{
    sql="SELECT user, password FROM users WHERE user=?"
    sql.setParam(1, myUser)
    return db.execute(sql)
}

在这种情况下,对于攻击者而言,输入任何棘手的值都将是没有用的,因为数据库引擎将透明地对待值 100%,而不会允许其中的任何控制字符它。