看看:

(来源:https://xkcd.com/327/)

这个SQL做什么:

Robert'); DROP TABLE STUDENTS; --

我知道'和——都是用来评论的,但是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的评论再次编辑

假设名称用于变量$ name。然后运行这个查询:

INSERT INTO Students VALUES ( '$Name' )

该代码错误地将用户提供的任何内容作为变量。你希望SQL是:

插入学生价值观(“罗伯特表格”)

但聪明的用户可以提供他们想要的任何东西:

INSERT INTO Students VALUES ('Robert');DROP TABLE Students;——”)

你得到的是:

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

——only注释该行的其余部分。

数据库的作者可能做了一个

sql = "SELECT * FROM STUDENTS WHERE (STUDENT_NAME = '" + student_name + "') AND other stuff";
execute(sql);

如果给出的是student_name,则使用名称“Robert”进行选择,然后删除表。“——”部分将给定查询的其余部分更改为注释。

它是这样工作的: 假设管理员正在查找学生的记录

Robert'); DROP TABLE STUDENTS; --

由于admin帐户拥有很高的权限,因此可以从该帐户中删除表。

从请求中检索用户名的代码是

现在查询是这样的(搜索student表)

String query="Select * from student where username='"+student_name+"'";

statement.executeQuery(query); //Rest of the code follows

生成的查询变成

Select * from student where username='Robert'); DROP TABLE STUDENTS; --

由于用户输入没有被净化,上面的查询被操作成两个部分

Select * from student where username='Robert'); 

DROP TABLE STUDENTS; --

双破折号(——)将注释掉查询的其余部分。

这是很危险的,因为如果存在密码验证,它会使密码验证无效

第一个会进行正常的搜索。

如果帐户有足够的权限,第二个将删除表student(通常学校管理帐户将运行这样的查询,并将具有上面讨论的权限)。

');结束查询,不开始注释。然后它删除students表,并注释本该执行的其余查询。