看看:
(来源:https://xkcd.com/327/)
这个SQL做什么:
Robert'); DROP TABLE STUDENTS; --
我知道'和——都是用来评论的,但是DROP这个词不是也会被评论吗?因为它是同一行的一部分。
看看:
(来源:https://xkcd.com/327/)
这个SQL做什么:
Robert'); DROP TABLE STUDENTS; --
我知道'和——都是用来评论的,但是DROP这个词不是也会被评论吗?因为它是同一行的一部分。
当前回答
假设你天真地写了一个学生创建方法,像这样:
void createStudent(String name) {
database.execute("INSERT INTO students (name) VALUES ('" + name + "')");
}
有人输入名字罗伯特’);降表学生;--
在数据库上运行的是这个查询:
INSERT INTO students (name) VALUES ('Robert'); DROP TABLE STUDENTS --')
分号结束插入命令并开始另一个;——注释掉了该行的其余部分。DROP TABLE命令被执行…
这就是为什么绑定参数是一个好东西。
其他回答
数据库的作者可能做了一个
sql = "SELECT * FROM STUDENTS WHERE (STUDENT_NAME = '" + student_name + "') AND other stuff";
execute(sql);
如果给出的是student_name,则使用名称“Robert”进行选择,然后删除表。“——”部分将给定查询的其余部分更改为注释。
');结束查询,不开始注释。然后它删除students表,并注释本该执行的其余查询。
假设你天真地写了一个学生创建方法,像这样:
void createStudent(String name) {
database.execute("INSERT INTO students (name) VALUES ('" + name + "')");
}
有人输入名字罗伯特’);降表学生;--
在数据库上运行的是这个查询:
INSERT INTO students (name) VALUES ('Robert'); DROP TABLE STUDENTS --')
分号结束插入命令并开始另一个;——注释掉了该行的其余部分。DROP TABLE命令被执行…
这就是为什么绑定参数是一个好东西。
单引号是字符串的开始和结束。分号是语句的结束。如果他们做这样的选择:
Select *
From Students
Where (Name = '<NameGetsInsertedHere>')
SQL将变成:
Select *
From Students
Where (Name = 'Robert'); DROP TABLE STUDENTS; --')
-- ^-------------------------------^
在某些系统上,select语句会先运行,然后是drop语句!信息是:不要嵌入值到你的SQL。而是使用参数!
它删除了学生表。
学校程序的原始代码可能看起来像这样
q = "INSERT INTO Students VALUES ('" + FNMName.Text + "', '" + LName.Text + "')";
这是向查询中添加文本输入的最简单的方法,非常糟糕,正如您将看到的那样。
值从第一个名字,中间名文本框FNMName。文本(是罗伯特的);降表学生;——)和姓氏文本框LName。文本(让我们称之为Derper)连接到查询的其余部分,结果实际上是两个查询由语句结束符(分号)分开。第二个查询已注入到第一个查询中。当代码对数据库执行此查询时,它将如下所示
INSERT INTO Students VALUES ('Robert'); DROP TABLE Students; --', 'Derper')
简单地说,就是这两个问题:
在student表中添加一条Name值为'Robert'的新记录
and
删除Students表
第二个查询之后的所有内容都被标记为注释:——','Derper')
学生名字中的'不是注释,而是结束字符串分隔符。因为学生的名字是一个字符串,所以在语法上需要它来完成假设的查询。只有当注入的SQL查询结果为有效SQL时,注入攻击才有效。
根据dan04的评论再次编辑