为什么""="利用这个MySQL查询?

Dan*_*son 7 php mysql security

在MySQL 5.6数据库上,我构建了这个简单的表并插入一行:

CREATE TABLE `users` ( 
`username` varchar(64) DEFAULT NULL, 
`password` varchar(64) DEFAULT NULL 
);

INSERT INTO users VALUES ('bob', 'pass');
Run Code Online (Sandbox Code Playgroud)

然后我在PHP中设置一个查询,如下所示:

$query = "SELECT * from users where username=\"".$username."\" and password=\"".$password."\"";
Run Code Online (Sandbox Code Playgroud)

$username$password它们都相等时""=",得到的查询是SELECT * from users where username="""="" and password="""="".当用于查询之前设置的表时,将返回表中的行.

问题是,MySQL如何评估该查询,使其认为查询有效并且WHERE语句为真?假设所有双引号都与最近的相邻双引号匹配,我原本期望查询被解释为类似这样,看起来应该被认为是乱码:

SELECT * from users where username=""
"="
" and password="
""
=
""
Run Code Online (Sandbox Code Playgroud)

以下是MySQL 5.6 DB上此行为的示例:http://sqlfiddle.com/#!9/02e606/2

Mar*_*c B 10

这是因为MySQL允许""作为替代品\".

mysql> select '"foo"' = """foo""", '"foo"' = "\"foo\"", 'foo' = """foo""";
+---------------------+---------------------+-------------------+
| '"foo"' = """foo""" | '"foo"' = "\"foo\"" | 'foo' = """foo""" |
+---------------------+---------------------+-------------------+
|                   1 |                   1 |                 0 |
+---------------------+---------------------+-------------------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

在您的具体情况:

SELECT * from users where username="""="" and password="""=""
Run Code Online (Sandbox Code Playgroud)

将是相同的(如果我在我脑海中正确解析这个):

SELECT * from users where (username='"="" and passsword="') = ""
Run Code Online (Sandbox Code Playgroud)

三向等式测试在语法上是正确的,但没有按预期进行评估

mysql> select 'a' = 'a' = 'a';
+-----------------+
| 'a' = 'a' = 'a' |
+-----------------+
|               0 |
+-----------------+
Run Code Online (Sandbox Code Playgroud)

因为它解析为(a=a)=a- > true=a- >false

- 评论@juan的后续行动:

mysql> select 'a'='a'='a', 'a'='a'='b', 'a'='b'='a', 'b'='a'='a', 'b'='b'='a';
+-------------+-------------+-------------+-------------+-------------+
| 'a'='a'='a' | 'a'='a'='b' | 'a'='b'='a' | 'b'='a'='a' | 'b'='b'='a' |
+-------------+-------------+-------------+-------------+-------------+
|           0 |           0 |           1 |           1 |           0 |
+-------------+-------------+-------------+-------------+-------------+
Run Code Online (Sandbox Code Playgroud)

这是非直观的,因为

mysql> select 'a'=('a'='b'), ('a'='a')='b', true='b', 'a'=false;
+---------------+---------------+----------+-----------+
| 'a'=('a'='b') | ('a'='a')='b' | true='b' | 'a'=false |
+---------------+---------------+----------+-----------+
|             1 |             0 |        0 |         1 |
+---------------+---------------+----------+-----------+
Run Code Online (Sandbox Code Playgroud)

---后续跟进:再次,您的原始查询:

SELECT * from users where username="""="" and password="""=""
Run Code Online (Sandbox Code Playgroud)

将运行为

SELECT * from users where (username='"="" and passsword="') = ""
SELECT * from users where (false) = ""
SELECT * from users where true
Run Code Online (Sandbox Code Playgroud)

因为false =""在mysql中求值为TRUE,因此包含所有行,除非你的用户名是字面意思"="" and password=".