当密码为空时,Windows 上的 PDO 会忽略主机名和用户名


PDO on Windows ignores host name and username when password is empty

我不确定我的设置是否有问题,或者这是Windows上PDO中的一个错误:

<?php 
$dsn = 'mysql:host=127.0.0.1;dbname=mydb;charset=UTF8';
$username = 'myuser';
$password = '';
$pdo = new PDO($dsn, $username, $password);

对我来说错误:

致命错误:未捕获的异常"PDOException",并显示消息 'SQLSTATE[42000] [1044] 拒绝用户 ''@'localhost' 访问 C 中的数据库 'mydb'' .php''ampps''www''test:6 堆栈跟踪:#0 C:''Ampps''www''test.php(6): PDO->__construct('mysql:host=127....', 'myuser', '') #1 {main} 在第 6 行抛出 C:''Ampps''www''test.php

我已经能够在所有 3 台 Windows 开发机器上重现它,但没有一台 Linux 服务器。

任何人都可以确认或指出可能是什么问题吗?

谢谢!

编辑:在具有空密码的用户上正确设置权限。

编辑2:有报告称该问题在运行MAMP 3.0.3的Mac上是可重现

编辑3:之前有几个报告,但看起来还没有被修复:

https://bugs.php.net/bug.php?id=43493

https://bugs.php.net/bug.php?id=46457

我的报告: https://bugs.php.net/bug.php?id=67026

EDIT4:当权限被授予"myuser

"@'localhost'时,它就可以工作,但是当权限被授予没有密码的'myuser'@'%'时,就会出现问题 - 在Linux上也是如此

我想

确认这一点。

在测试之前,请确保满足条件:

  1. 确保nonexistent_user不是数据库中的用户。
  2. 确保根设置了密码。
  3. 请确保单独运行这些测试。
  4. 确保在 Windows(或任何受影响的计算机)上运行这些测试。

我已经加粗了有问题的用户名。

测试 #1

不存在的用户 + 空密码 = 错误消息的空用户名

$mysqli = new Mysqli('localhost', 'nonexistent_user', '', 'database');
$pdo    = new PDO('mysql:host=localhost;dbname=database;charset=UTF8', 'nonexistent_user', '');
警告:mysqli:

:mysqli():(HY000/1044):用户"@'localhost'在测试中访问数据库"数据库"被拒绝.php

致命错误:未捕获的异常"PDOException",消息为"SQLSTATE[HY000] [1044] 用户"@'localhost'在测试中拒绝访问数据库'数据库'.php堆栈跟踪: #0 test.php(): PDO->__construct('mysql:host=loca...', 'nonexistent_use...', '') #1 {main} 在测试中抛出.php

测试 #2

存在的用户 + 空密码 = 为错误消息设置的用户名

$mysqli = new Mysqli('localhost', 'root', '', 'database');
$pdo    = new PDO('mysql:host=localhost;dbname=database;charset=UTF8', 'root', '');
警告:mysqli:

:mysqli():(HY000/1045):在测试中拒绝用户"root"@'localhost"(使用密码:NO)的访问.php

致命错误:未捕获的异常"PDOException",消息为"SQLSTATE[HY000] [1045] 测试中用户"root"@"localhost"(使用密码:NO)的访问被拒绝.php堆栈跟踪:#0 test.php(): PDO->__construct('mysql:host=loca...', 'root', '') #1 {main} 在测试中抛出.php

测试 #3

不存在的用户 + 设置密码 = 为错误消息设置的用户名

$mysqli = new Mysqli('localhost', 'nonexistent_user', 'password', 'database');
$pdo    = new PDO('mysql:host=localhost;dbname=database;charset=UTF8', 'nonexistent_user', 'password');
警告:mysqli:

:mysqli():(HY000/1045):在测试中拒绝用户"nonexistent_user"@"localhost"(使用密码:YES)的访问.php

致命错误:未捕获的异常"PDOException",消息为"SQLSTATE[HY000] [1045] 测试中拒绝用户"nonexistent_user"@'本地主机'(使用密码:YES)"的访问.php堆栈跟踪:#0 test.php(): PDO->__construct('mysql:host=loca...', 'nonexistent_use...', 'password') #1 {main} 在测试中抛出.php

当用户不存在且提供空密码时,错误消息将显示空白用户名。

我觉得这将是一个安全风险,因为攻击者可能会通过发送带有空密码的测试用户名来测试哪些用户是有效的,并查看用户名的错误响应是否为空。

问题不在于PHP或PDO,我能够直接使用MySQL重现该问题。

如果有"@'localhost'用户,

可以使用任何没有密码的用户名登录,任何用户@'%'将在登录时被忽略。

繁殖步骤:https://gist.github.com/sellvana/9989227