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=".