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

标签 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');

然后我像这样在 PHP 中设置查询:

$query = "SELECT * from users where username=\"".$username."\" and password=\"".$password."\"";

$username$password都等于""="时,结果查询是SELECT * from users where username="""=""and password="""=""。用于查询之前设置的表时,返回表中的行。

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

SELECT * from users where username=""
"="
" and password="
""
=
""

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

最佳答案

这是因为 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)

在您的具体情况下:

SELECT * from users where username="""="" and password="""=""

将与(如果我在脑海中正确解析)相同:

SELECT * from users where (username='"="" and passsword="') = ""

三向相等性测试在语法上是正确的,但未按预期进行评估

mysql> select 'a' = 'a' = 'a';
+-----------------+
| 'a' = 'a' = 'a' |
+-----------------+
|               0 |
+-----------------+

因为它解析为 (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 |
+-------------+-------------+-------------+-------------+-------------+

这是不直观的,因为

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 |
+---------------+---------------+----------+-----------+

--- followup to the followup: again, your original query:

SELECT * from users where username="""="" and password="""=""

将运行为

SELECT * from users where (username='"="" and passsword="') = ""
SELECT * from users where (false) = ""
SELECT * from users where true

因为 mysql 中的 false ="" 计算结果为 TRUE,因此所有行都被包括在内,除非您的用户名是 "=""和 password=".

关于php - 为什么 ""="利用这个 MySQL 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39923935/

相关文章:

php - 将配置文件与 Paypal SDK 一起使用会抛出 PayPalInvalidCredentialException

.net - 迁移 .NET/MySQL 应用程序。到 DB2

php - URL 和 mod_rewrite : use many special chars and keep data safe from attacks

PHP 编辑数据库条目不更新

javascript - 更改 HTML 表中 td 元素的颜色,然后使用 AJAX 写入数据库

php - PHP解析/语法错误;以及如何解决它们

mysql - 如何连接两个表并在第三个表中显示结果

php - 简单的 php PDO 目录名称无效 : 1046 No database selected

c - 故障转储上的明文密码保护

c++ - 只允许来自 RFID 阅读器 C++ 的输入