必须立即删除所有匿名用户并清空mysql.db中对应权限、执行flush privileges。匿名用户user值为空字符串''而非null,需用where user = ''查询;须逐一删除''@'localhost'、''@'127.0.0.1'、''@'::1'等;drop user不清理mysql.db表,残留权限可致攻击者创建test库写入数据;docker/systemd下自动刷新不可靠,flush privileges必须显式执行。

必须立刻删除,不能只跑 mysql_secure_installation 就以为完事了。 它能删掉一部分,但残留的空用户名、mysql.db 表里的旧权限、未刷新的内存缓存,三者任一存在都会让漏洞继续生效。
怎么查出所有匿名用户
匿名用户不是 NULL,而是空字符串 '',用 IS NULL 会完全漏掉:
- 正确检查语句只有这一条:
SELECT User, Host FROM mysql.user WHERE User = ''; - 返回结果里只要
User列是空的,不管Host是'localhost'、'127.0.0.1'还是'::1',全都要处理 - 别信“只删
''@'localhost'就够了”——IPv6 的''@'::1'和通配符''@'%'同样危险,且常被忽略
删匿名用户必须三步一起走
只执行 DROP USER 或只删 mysql.user 行,都等于白干:
- 先删账号:
DROP USER ''@'localhost'; DROP USER ''@'127.0.0.1'; DROP USER ''@'::1';(注意大小写和引号要和查询结果完全一致) - 再清库级权限:
DELETE FROM mysql.db WHERE User = '';(DROP USER不动mysql.db,残留权限能让攻击者重建test库并写入数据) - 最后强制重载:
FLUSH PRIVILEGES;(Docker / systemd 环境下自动刷新不可靠,这句必须显式执行)
删完还连得上?可能不是没删干净
常见错觉:删了 ''@'localhost',但 mysql -u root -p 还是免密进。大概率是因为 root@'localhost' 用了 auth_socket 插件,跟匿名用户无关:
- 验证方式:
SELECT User, Host, plugin FROM mysql.user WHERE User = 'root' AND Host = 'localhost'; - 如果是
auth_socket,需改认证:ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'your_password';,再FLUSH PRIVILEGES; - 更隐蔽的风险:某些老旧应用脚本硬编码了
-u '' -h localhost,删完直接断连——得同步改代码,不能只修数据库
真正容易被跳过的,是第二步删 mysql.db 权限。很多团队跑完脚本、删完用户、FLUSH 了,就去喝咖啡,结果攻击者连上来一句 CREATE DATABASE test;,再往里灌数据,权限全在。











