以下查询返回表tbl_user中的所有密码,但我无法理解为什么会发生这种情况。
SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1 -- '
请帮助我理解这部分问题:' admin'或1 = 1 - '
你能介绍其他类似的威胁(网站,书籍等)吗?
答案 0 :(得分:8)
这是一个经典的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
没有注入),您可以使用admin_name和superadmin权限的user_name为用户提取密码。您现在已经评论过,并且它没有被执行。这就是整个密码表的返回方式。
答案 1 :(得分:5)
逻辑OR
的结果如下:
a | b | a OR b
-----------------------
false | false | false
false | true | true
true | false | true
true | true | true
如果其中一个操作数为真,则OR b的结果计算结果为true。
1 = 1 evaluates to true
=>
(any expression) OR 1 = 1 evaluates to true
=>
name = 'admin' OR 1 = 1
对于表格的每一行,评估为true
结果:
SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1 -- '
将返回所有用户的密码,不仅仅是管理员,因为正如PeeHaa所述
--
是sql评论的开头。
答案 2 :(得分:2)
我可以想象你在这里遇到两种可能的混淆。第一个是,正如其他人所提到的,只要 expr1 OR expr2
或expr1
为真,expr2
就会返回true。由于1=1
始终为true,因此对于表中的每条记录,您的WHERE
语句都将为true。
您可能会感到困惑的第二件事是查询中的最后-- '
。 --
是PHP中与//
等效的SQL;它表示该行的其余部分是注释,应该被忽略。所以SQL解释器只读取SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1
而忽略了行的其余部分,这就是为什么尾随单引号不会导致语法错误。
此处唯一的安全风险是您将未转义的用户输入传递给SQL。在SQL查询中使用它之前,始终使用mysqli_real_escape_string或等效函数转义任何用户输入。
编辑:正如评论中所指出的,参数化查询通常比手动转义每个输入元素更好。 PHP的PDO扩展是开始这种方法的好地方。
答案 3 :(得分: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
以这种方式工作,如果任何条件为真,则表示整个表达式为真。在表达式name = 'admin' OR true
中,一个表达式为真(true为真),因此整个表达式为true
所以查询现在可以是
SELECT password FROM tbl_users WHERE true
现在,如果我们看看我们有WHERE true
的部分。这意味着事实上没有条件,所以我们可以将查询更改为:
SELECT password FROM tbl_users
因此,当您看到您的查询简单时,为表中的每条记录获取列password
(可能适用于所有用户)
答案 4 :(得分:-2)
我认为你正在寻找'AND'而不是'OR'
'OR'表示其中一个条件(WHERE name ='admin'OR 1 = 1)必须为true,在这种情况下,它返回名称等于'admin'或者有1的所有条件等于1。
请尝试使用此代码:
SELECT password FROM tbl_users WHERE name = 'admin' AND 1=1