以下查询返回表tbl_user中的所有密码,但我无法理解为什么会发生这种情况。'admin'的含义是什么OR 1 = 1 - '
SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1 -- '
请帮助我理解查询的这个部分: '管理员' OR 1 = 1 - '
你能介绍其他威胁这样的(网站,书籍等)?
以下查询返回表tbl_user中的所有密码,但我无法理解为什么会发生这种情况。'admin'的含义是什么OR 1 = 1 - '
SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1 -- '
请帮助我理解查询的这个部分: '管理员' OR 1 = 1 - '
你能介绍其他威胁这样的(网站,书籍等)?
这是一个经典的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用户。你现在已经发表了评论,并没有被执行。这就是整个密码表可以被返回的方式。
非常好,不仅逻辑部分 - 我认为我做得很好 - 但是这种利用如何改变查询的意图以及如何扩展。 – VMai
我认为你正在寻找“和”而不是“或”
“OR”表示的条件之一(其中name =“管理员” OR 1 = 1)必须是真实的,并在此情况下,它返回具有名称等于“管理员”的一切,或具有1等于1
尝试使用此来代替:
SELECT password FROM tbl_users WHERE name = 'admin' AND 1=1
的逻辑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注释的。
有两种可能的混淆,我可以想象你在这里遇到。第一个是,正如其他人所提到的,只要或者expr1
或expr2
为真,则返回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扩展是以这种方式开始的好地方。
IMO,最好使用参数化而不是转义和串联 - 后者应该只用于不能被参数化的东西,比如列名。 – halfer
@halfer我同意,参数化优于转义+串联作为编码实践,因为错误更难。我将编辑它的参考到答案中。 –
最后部分-- '
是注释,所以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
所以(可能为所有用户)
也就是说一个经典的SQL注入。它返回名称为'admin' * OR *的用户,其中1 = 1(因为1确实每个记录匹配1)。'--'只是在将它看作是注释之后才确认eveyrthing – PeeHaa
您可以删除1 = 1,因为它什么也不做。 – Gadgetster
@Gadgetster你是什么意思? – PeeHaa