看看:

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

这个SQL做什么:

Robert'); DROP TABLE STUDENTS; --

我知道'和——都是用来评论的,但是DROP这个词不是也会被评论吗?因为它是同一行的一部分。


当前回答

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

INSERT INTO Students VALUES ( '$Name' )

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

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

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

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

你得到的是:

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

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

其他回答

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

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

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

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

在本例中,'不是注释字符。它用于分隔字符串字面量。漫画艺术家的想法是,学校在某个地方有动态sql,看起来像这样:

$sql = "INSERT INTO `Students` (FirstName, LastName) VALUES ('" . $fname . "', '" . $lname . "')";

现在'字符在程序员期望它之前结束了字符串字面量。结合;字符来结束语句,攻击者现在可以添加(注入)任何他们想要的SQL。末尾的——注释是为了确保原始语句中任何剩余的sql都不会阻止在服务器上编译查询。

FWIW,我还认为漫画中有一个重要的细节是错误的:如果你像漫画中建议的那样清理数据库输入,你仍然是错的。相反,您应该考虑隔离数据库输入,正确的方法是通过参数化查询/准备好的语句。

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

INSERT INTO Students VALUES ( '$Name' )

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

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

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

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

你得到的是:

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

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

单引号是字符串的开始和结束。分号是语句的结束。如果他们做这样的选择:

Select *
From Students
Where (Name = '<NameGetsInsertedHere>')

SQL将变成:

Select *
From Students
Where (Name = 'Robert'); DROP TABLE STUDENTS; --')
--             ^-------------------------------^

在某些系统上,select语句会先运行,然后是drop语句!信息是:不要嵌入值到你的SQL。而是使用参数!