空密码账号即数据库大门未锁,须用TRIM(authentication_string)=0或IN('','*')精准识别;含''@'localhost'或host='%'者优先标记;auth_socket用户属正常免密机制,勿误删。

空密码账号等于数据库大门不锁,只要网络可达就能直连登录。必须用 authentication_string 字段查,不能看 Password(5.7+ 已废弃,8.0 已移除),也不能只比对 ''——攻击者会塞空格伪装。
查 authentication_string 为空、'*' 或 NULL 的账号
MySQL 5.7+ 完全依赖 authentication_string 判断是否设密。''、'*'、NULL 都代表无密码;但空格填充(如 ' ')会让 LENGTH(authentication_string) > 0 却实际无密,所以必须用 TRIM()。
- 执行:
SELECT host, user, plugin, authentication_string FROM mysql.user WHERE LENGTH(TRIM(authentication_string)) = 0 OR authentication_string IN ('', '*'); - 结果中若含
user = ''(如''@'localhost'),是典型匿名空密码入口,优先标记 - 该查询需以具备
SELECT ON mysql.*权限的账号(如root)执行,普通账号查不到mysql.user -
mysql.session和mysql.sys这类内置账号的authentication_string固定为占位符(如'*THISISNOTAVALID%'),属正常,不用处理
区分 auth_socket 用户:它根本没密码,但不是漏洞
Ubuntu/CentOS 新装 MySQL 常见 root 用户插件为 auth_socket,此时 authentication_string 为空或无效,不代表“空密码”,而是靠 Unix socket 文件校验系统用户身份,本地免密登录是设计行为。
安装、修复、更新或打包一个基于 Python 和 PyMySQL 实现的 Windows `mysql` 命令。适用于用户希望在 PowerShell/CMD 中输入 `mysql` 时重定向到 Python 实现、需要交互式输入 MySQL 连接信息、需要同步到当前用户本地 bin 目录,或需要将该能力封装成可公开复用的 Codex skill。
- 查这类账号:
SELECT user, host, plugin FROM mysql.user WHERE plugin = 'auth_socket'; - 若需密码登录(比如远程连接或某些客户端),必须先切换插件:
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_strong_password'; - 直接对
auth_socket用户执行ALTER USER ... IDENTIFIED BY会报错ERROR 1396 (HY000): Operation ALTER USER failed
删之前必须确认 CURRENT_USER() 和 SHOW GRANTS
别一看到 ''@'localhost' 就 DROP ——你当前可能正用它登录。删错会导致自己被锁死。
- 先执行:
SELECT USER(), CURRENT_USER();—— 若CURRENT_USER()返回''@'localhost',说明你正通过该账号登录 - 对每个可疑账号运行:
SHOW GRANTS FOR ''@'localhost';(注意必须带完整@'host'),看是否只有USAGE,还是绑了ALL PRIVILEGES - 即使
SHOW GRANTS只返回USAGE,也不能掉以轻心:查mysql.role_edges确认它是否通过角色继承高权(例如TO_ROLE = 'dba') - 确认无误后,精确删除:
DROP USER ''@'localhost';,再FLUSH PRIVILEGES;
别漏掉 host = '%' 配合空密码的组合
空密码本身危险,但如果还配 host = '%',等于把钥匙扔在公网路口。这类账号在扫描日志里出现频率极高。
- 补充检查语句:
SELECT user, host, authentication_string FROM mysql.user WHERE (authentication_string = '' OR authentication_string = '*') AND host = '%'; - 这类账号往往不是人建的,而是旧版初始化脚本遗留、自动化部署模板未清理,或 SQL 注入后植入
- 发现后不要仅改密码,应直接
DROP USER—— 因为host = '%'本身已违反最小权限原则 - 生产环境应禁用所有
host = '%'的管理账号;业务账号如需远程访问,必须限定 CIDR(如'app_user'@'192.168.10.0/24')
真正难的不是找出空密码账号,而是判断哪个该删、哪个该改认证方式、哪个其实正在承担关键运维路径。每次操作前,CURRENT_USER() 和 SHOW GRANTS FOR ... 必须成对验证,少一步就可能中断服务。

















