应查三类特征:权限远超业务需要、最近登录时间可疑、认证插件异常;drop user后仍能连接因角色残留或代理权限未清理,需同步清空mysql.db等权限表并逐个删除各host变体。

怎么确认黑客留下的后门账号不是“空用户名”而是伪装成合法用户?
黑客提权后常建一个看似正常的账号,比如 admin@'10.%.%.%' 或 backup@'localhost',但权限极大、登录时间异常、或绑定高危角色。不能只盯着 User = '',得查三类特征:
- 权限远超业务需要:比如对
mysql库有INSERT,UPDATE,DELETE,或拥有FILE、SHUTDOWN、SUPER等高危权限 - 最近登录时间可疑:用
performance_schema.accounts查last_seen,若为 2026-06-28 23:59 这类整点时间,且与你运维操作无关,大概率是扫描器或木马触发的 - 认证插件异常:查
plugin字段是否为mysql_native_password以外的冷门插件(如自定义 UDF 加载的插件),或account_locked = 'N'但长期无交互
执行这句查所有非系统、非空、非 root 的高权限候选账号:SELECT User, Host, plugin, account_locked, authentication_string FROM mysql.user WHERE User NOT LIKE 'mysql.%' AND User != '' AND User != 'root' AND (Select_priv = 'Y' OR Insert_priv = 'Y' OR Update_priv = 'Y' OR Delete_priv = 'Y' OR File_priv = 'Y');
为什么 DROP USER 后仍能连上?可能是角色残留或代理权限没清理
黑客常通过角色间接授予权限,删账号本身不等于断掉权限链。比如他给 backdoor@'%' 授了 dba_role,而 dba_role 又被授予 CREATE USER 和 GRANT OPTION ——删掉账号后,角色还在,别人再建同名账号可能继承权限。
- 先查角色绑定:
SELECT FROM_USER, TO_USER FROM mysql.role_edges WHERE FROM_USER = 'backdoor'; - 再查谁被这个角色授权:
SELECT * FROM mysql.role_edges WHERE TO_USER = 'dba_role'; - 检查代理关系:
SELECT * FROM mysql.proxies_priv WHERE CONCAT(User, '@', Host) = 'backdoor@%'; - 如果发现角色被其他账号依赖,别直接删角色,先
REVOKE dba_role FROM 'backdoor'@'%';,再DROP USER 'backdoor'@'%';
删完账号后必须立刻检查 mysql.db 和 mysql.tables_priv 是否还有残留
DROP USER 在 MySQL 8.0+ 会清理 mysql.user 和 mysql.global_grants,但不会碰 mysql.db 表里 User = 'backdoor' 的库级权限记录。这些残留条目会让新创建的同名账号自动获得旧权限,等于白删。
- 手动清库级权限:
DELETE FROM mysql.db WHERE User = 'backdoor'; - 清表级权限:
DELETE FROM mysql.tables_priv WHERE User = 'backdoor'; - 清列级权限:
DELETE FROM mysql.columns_priv WHERE User = 'backdoor'; - 最后强制重载:
FLUSH PRIVILEGES;(注意:这里必须执行,因为上面是 DML 操作,不是 DDL)
最容易被忽略的后门入口:host 匹配宽松 + IPv6 地址绕过
黑客喜欢建 'hacker'@'%',你以为删了就完事,但他可能还留了 'hacker'@'::1'(IPv6 localhost)、'hacker'@'127.0.0.1'、甚至 'hacker'@'10.0.0.%'。MySQL 的 host 匹配是逐条比对的,'%' 不覆盖具体 IP。
- 查全量 host 分布:
SELECT User, Host FROM mysql.user WHERE User = 'hacker'; - 逐个删除,不要省略 host:
DROP USER 'hacker'@'::1'; DROP USER 'hacker'@'127.0.0.1'; DROP USER 'hacker'@'10.0.0.%'; - 特别注意大小写和引号:查询结果里是
'HACKER'@'localhost',你就得写DROP USER 'HACKER'@'localhost';,否则静默失败
真正麻烦的不是账号本身,而是它可能被硬编码在某个没上线的测试脚本、备份恢复工具、或监控 agent 的配置里——删完第二天应用突然连不上,才发现是某台老服务器的 cron 每小时调一次 mysql -u hacker -p... -e "SELECT 1"。动手前,先 grep 全局代码和配置目录里的用户名。











