下面的查询返回表tbl_user中的所有密码,但我不明白为什么会发生这种情况。
SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1 -- '
请帮助我理解查询的这一部分:'admin' 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为admin和superadmin权限的用户提取密码。现在已经将其注释掉了,它不会被执行。这就是返回整个密码表的方式。
逻辑OR
的结果如下:
a | b | a OR b
-----------------------
false | false | false
false | true | true
true | false | true
true | true | true
如果其中一个操作数为真,则a或b的运算结果为真。
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 -- '
将返回所有用户的密码,而不仅仅是admin,因为正如PeeHaa
所述--
是SQL注释的开始
我可以想象你在这里遇到两种可能的困惑。第一个是,正如其他人提到的,当 expr1
或expr2
为真时,expr1 OR expr2
返回真。因为1=1
总是为真,所以WHERE
语句对表中的每条记录都为真。
您可能感到困惑的第二件事是查询中的最后一个-- '
。--
在SQL中相当于PHP中的//
;它表示该行的其余部分是注释,应该忽略。因此,SQL解释器只读取SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1
,而忽略该行的其余部分,这就是为什么后面的单引号不会导致语法错误。
编辑:正如在注释中指出的,参数化查询通常是比手动转义每个输入元素更好的实践。PHP的PDO扩展是一个很好的开始。
最后一部分-- '
是注释,所以MySQL不关心。所以我们没有left
SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1
在这个查询中1=1
是true,因为1和1是一样的。当然,这里也可以是另一个true表达式,例如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部分,我们有WHERE true
。这意味着事实上没有条件,因此我们可以将query更改为:
SELECT password FROM tbl_users
因此,正如您所看到的,您的查询简单地获取列password
在您的表中的每条记录(可能为所有用户)
我想你是在寻找'AND'而不是'OR'
'OR'表示其中一个条件(WHERE name = 'admin'或1=1)必须为真,在这种情况下,它将返回name等于'admin'或1等于1的所有内容。
试着用这个代替:
SELECT password FROM tbl_users WHERE name = 'admin' AND 1=1