2014-07-19 68 views
3

以下查询返回表tbl_user中的所有密码,但我无法理解为什么会发生这种情况。'admin'的含义是什么OR 1 = 1 - '

SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1 -- ' 

请帮助我理解查询的这个部分: '管理员' OR 1 = 1 - '

你能介绍其他威胁这样的(网站,书籍等)?

+3

也就是说一个经典的SQL注入。它返回名称为'admin' * OR *的用户,其中1 = 1(因为1确实每个记录匹配1)。'--'只是在将它看作是注释之后才确认eveyrthing – PeeHaa

+0

您可以删除1 = 1,因为它什么也不做。 – Gadgetster

+0

@Gadgetster你是什么意思? – PeeHaa

回答

6

这是一个经典的SQL注入。 SQLfiddle

在这个例子中,有5个用户被添加到表:

听我的解释是看到这个小提琴。然后您的查询运行。预期结果将仅返回admin用户的密码值。

但是,通过添加1=1(这是一个真实的语句),将返回所有密码。

帮助可视化的另一种方法是添加括号,以便您可以看到如何评估所有内容。

SELECT pass FROM users WHERE (user_name = 'admin')    OR (1=1) -- ' 
           ^Pulls only the admin user  ^Pulls everything because 1=1 

所以,我们选择在这里用户名是admin表中的密码。我们也从1 = 1的表格中提取密码 - 这总是正确的。每行评估为true,因此所有密码都会返回。

最后的-- '用于注释掉其余的查询。

SELECT pass from users WHERE user_name = 'admin' or (1=1) -- 'and permission='superadmin' 

通常情况下,(如果1=1没有被注入),你会拉密码与管理员和超级管理员权限USER_NAME用户。你现在已经发表了评论,并没有被执行。这就是整个密码表可以被返回的方式。

+0

非常好,不仅逻辑部分 - 我认为我做得很好 - 但是这种利用如何改变查询的意图以及如何扩展。 – VMai

-2

我认为你正在寻找“和”而不是“或”

“OR”表示的条件之一(其中name =“管理员” OR 1 = 1)必须是真实的,并在此情况下,它返回具有名称等于“管理员”的一切,或具有1等于1

尝试使用此来代替:

SELECT password FROM tbl_users WHERE name = 'admin' AND 1=1 
+4

该查询确实不是原作者的意图 - 它是一种流行的破解语法,旨在利用SQL注入漏洞在所有情况下返回行。在这种情况下,“OR”形式就是黑客想要的。 – halfer

+0

噢好吧,对不起,我对这个东西很陌生,只是试图从我认识的小孩身上得到帮助。谢谢你告诉我。 – Duane

+0

不用担心。如果'1 = 1'_preceded_'WHERE'子句的其余部分 - 如果查询构建器库具有一个包含多个可选子句的永久子句,那么您会很对。这是因为它简化了附加语法 - 所有新的子句都是以“AND(clause)”的形式出现的。 – halfer

4

的逻辑OR的结果如下:

a  | b  | a OR b 
----------------------- 
false | false | false 
false | true | true 
true | false | true 
true | true | true 

如果其中一个操作数为真,则OR b的结果为真。

1 = 1 evaluates to true 

=>

(any expression) OR 1 = 1 evaluates to true 

=>

name = 'admin' OR 1 = 1 

计算结果为真为你的表的每一行

结果:

SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1 -- ' 

将返回密码,所有用户,不仅是管理,因为PeeHaa

作为陈述
-- 

是开始SQL注释的。

2

有两种可能的混淆,我可以想象你在这里遇到。第一个是,正如其他人所提到的,只要或者expr1expr2为真,则返回true。由于1=1始终为真,因此您的WHERE语句对于表中的每个记录均为真。

您可能会困惑的第二件事是查询中的最后一个-- '--是PHP中的//的SQL等效项;它表示该行的其余部分是注释,应该忽略。所以SQL解释器只读SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1而忽略了其余部分,这就是为什么尾部单引号不会导致语法错误的原因。

这里唯一的安全风险是如果您将未转义的用户输入传递给SQL。在SQL查询中使用它之前,请始终使用mysqli_real_escape_string或等效函数转义任何用户输入。

编辑:正如在注释中指出的,参数化查询通常比手动转义每个输入元素更好。 PHP的PDO扩展是以这种方式开始的好地方。

+1

IMO,最好使用参数化而不是转义和串联 - 后者应该只用于不能被参数化的东西,比如列名。 – halfer

+1

@halfer我同意,参数化优于转义+串联作为编码实践,因为错误更难。我将编辑它的参考到答案中。 –

0

最后部分-- '是注释,所以MySQL不关心。所以我们没有留下

SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1 

在此查询1=1是真实的,因为1是同样是1这可能是这里当然另一个真实的表达,例如2=2'a'='a' - 结果将是始终不变的。

所以您的查询看起来是这样的:

SELECT password FROM tbl_users WHERE name = 'admin' OR true 

操作OR以这种方式工作,如果有任何的条件是事实,就意味着整个表达式为true。在表达name = 'admin' OR true一个表达式为true(真实不虚),所以这整个表达式是true

所以查询现在可能是

SELECT password FROM tbl_users WHERE true 

现在,如果我们看看那里的一部分,我们有WHERE true。这意味着事实上没有条件,所以我们可以改变查询到:正如你在表格中看到您的查询简单的获得列password每个记录

SELECT password FROM tbl_users 

所以(可能为所有用户)

+0

不好意思,你能帮我理解为什么下面的查询不起作用吗? 'SELECT name FROM list WHERE name = true - '' – Daniyal

+0

@Daniyal,如果你有问题,请随时解释发生了什么(错误?没有?崩溃?等)。在这种情况下,您可能会比较字符串列和布尔常量。 – halfer

+0

@halfer非常感谢MR @Marrcin,对不起,你能帮我理解为什么下面的查询返回一个空的结果集? 'SELECT name FROM list WHERE name = true - '' – Daniyal

相关问题