看看:
(来源:https://xkcd.com/327/)
这个SQL做什么:
Robert'); DROP TABLE STUDENTS; --
我知道'和——都是用来评论的,但是DROP这个词不是也会被评论吗?因为它是同一行的一部分。
看看:
(来源:https://xkcd.com/327/)
这个SQL做什么:
Robert'); DROP TABLE STUDENTS; --
我知道'和——都是用来评论的,但是DROP这个词不是也会被评论吗?因为它是同一行的一部分。
当前回答
在本例中,'不是注释字符。它用于分隔字符串字面量。漫画艺术家的想法是,学校在某个地方有动态sql,看起来像这样:
$sql = "INSERT INTO `Students` (FirstName, LastName) VALUES ('" . $fname . "', '" . $lname . "')";
现在'字符在程序员期望它之前结束了字符串字面量。结合;字符来结束语句,攻击者现在可以添加(注入)任何他们想要的SQL。末尾的——注释是为了确保原始语句中任何剩余的sql都不会阻止在服务器上编译查询。
FWIW,我还认为漫画中有一个重要的细节是错误的:如果你像漫画中建议的那样清理数据库输入,你仍然是错的。相反,您应该考虑隔离数据库输入,正确的方法是通过参数化查询/准备好的语句。
其他回答
不,'在SQL中不是注释,而是分隔符。
妈妈假设数据库程序员的请求是这样的:
INSERT INTO 'students' ('first_name', 'last_name') VALUES ('$firstName', '$lastName');
(例如)添加新的student,其中$xxx变量内容直接从HTML表单中取出,不检查格式也不转义特殊字符。
如果$firstName包含Robert');DROP TABLE student;——数据库程序将直接在DB上执行以下请求:
INSERT INTO 'students' ('first_name', 'last_name') VALUES ('Robert'); DROP TABLE students; --', 'XKCD');
ie。它会提前终止插入语句,执行黑客想要的任何恶意代码,然后注释掉可能存在的任何剩余代码。
嗯,我太慢了,我已经看到了8个答案在我之前的橙色带…:-)似乎是一个流行的话题。
数据库的作者可能做了一个
sql = "SELECT * FROM STUDENTS WHERE (STUDENT_NAME = '" + student_name + "') AND other stuff";
execute(sql);
如果给出的是student_name,则使用名称“Robert”进行选择,然后删除表。“——”部分将给定查询的其余部分更改为注释。
它删除了学生表。
学校程序的原始代码可能看起来像这样
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的评论再次编辑
正如其他人已经指出的那样,the ');关闭原来的语句,然后第二个语句紧随其后。到目前为止,大多数框架(包括PHP等语言)都有默认的安全设置,不允许在一个SQL字符串中包含多条语句。例如,在PHP中,您只能使用mysqli_multi_query函数在一个SQL字符串中运行多条语句。
但是,您可以通过SQL注入操作现有的SQL语句,而无需添加第二条语句。假设你有一个登录系统,它检查用户名和密码,简单的选择:
$query="SELECT * FROM users WHERE username='" . $_REQUEST['user'] . "' and (password='".$_REQUEST['pass']."')";
$result=mysql_query($query);
如果你提供peter作为用户名,secret作为密码,得到的SQL字符串将如下所示:
SELECT * FROM users WHERE username='peter' and (password='secret')
一切都很好。现在,假设您提供以下字符串作为密码:
' OR '1'='1
然后得到的SQL字符串将是这样的:
SELECT * FROM users WHERE username='peter' and (password='' OR '1'='1')
这将使您可以在不知道密码的情况下登录任何帐户。因此,为了使用SQL注入,您不需要能够使用两条语句,尽管如果您能够提供多条语句,您可能会做更多破坏性的事情。
SQL中的'字符用于字符串常量。在本例中,它用于结束字符串常量,而不是用于注释。