MySQL 5.7起弃用password字段,8.0完全移除,密码统一存于authentication_string字段且为插件相关哈希值,明文比对必然失败;空值(''或'*')及弱口令哈希需结合plugin字段识别并按插件类型安全重置。

直接查 authentication_string 字段比对已知弱口令哈希值,是最准、最安全的验证方式——不触发登录、不依赖网络、不暴露行为。
为什么不能直接查 password 字段或用明文比对
MySQL 5.7 起已弃用 password 字段,8.0 完全移除;所有密码以插件相关哈希形式存于 authentication_string。试图用明文(如 '123456')直接匹配该字段必然失败——它存的是哈希,不是原文。
- 不同认证插件生成的哈希不可互换:
mysql_native_password和caching_sha2_password对同一明文密码输出完全不同 -
authentication_string值为''或'*'表示空密码,属于高危状态,需立即处理 - 旧版迁移后若未重置密码,可能残留
'*'占位符,TRIM()+ 长度判断能有效识别
查空密码和通配符账号的最小安全查询
执行以下语句必须使用具备 SELECT ON mysql.* 权限的账号(通常是 root):
SELECT host, user, plugin, authentication_string
FROM mysql.user
WHERE LENGTH(TRIM(authentication_string)) = 0
OR authentication_string IN ('', '*');-
TRIM()防止攻击者用空格填充伪装成“非空”密码 -
plugin字段要一并查出,因为后续加固需按插件类型重置密码(例如caching_sha2_password用户不能用SET PASSWORD简单赋值) - 结果中若含
host = '%'且user非'root',大概率是误配,应限制主机范围或删掉
比对常见弱口令哈希值的可执行查询
仅适用于已知插件类型环境。例如确认实例用的是 mysql_native_password,才可用如下哈希列表筛查:
SELECT host, user, plugin, authentication_string FROM mysql.user WHERE authentication_string IN ( '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9', -- 123456 '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19', -- password '*AAB0484EA8719F782B12F5E181243E343312410A' -- 12345678 );
- 哈希值区分大小写,复制时别漏字符或改大小写
- 如果实例默认插件是
caching_sha2_password,上面的哈希全无效;得用对应算法重新计算(例如用openssl或 Python 的cryptography库) - 生产环境禁用
caching_sha2_password_auto_generate_rsa_keys=OFF,否则明文传输风险仍在
容易被忽略的权限与执行前提
即使 SQL 写对了,也会因权限或配置卡住:
- 普通账号无法访问
mysql.user表,报错ERROR 1142 (42000): SELECT command denied to user - MySQL 8.0 默认关闭
secure_file_priv,但这里不涉及文件操作,无需调整 - 若启用了 SELinux 或 AppArmor,且策略过于严格,
SELECT FROM mysql.*可能被拦截(少见但存在) - 远程连接时注意:MySQL 客户端默认启用
--ssl-mode=REQUIRED(8.0.29+),若服务端未配 SSL,需显式加--ssl-mode=DISABLED
真正麻烦的不是查不出弱口令,而是查出来之后不知道该用哪个插件语法重置、不敢动 plugin 字段、或者重置后应用连不上——这些细节比查询本身更常导致回滚。


















