生产环境排查弱口令必须只读元数据、本地离线比对、避开明文密码:禁止使用hydra等爆破工具以防触发告警;唯一安全起点是SELECT User,Host,authentication_string FROM mysql.user,重点识别空密码、匿名用户、特权账号泛权限三类高危信号,并离线分析哈希强度与策略合规性。

生产环境里不能跑爆破工具,也不能开 general_log 记所有操作——排查弱口令必须「不动声色、有据可查、不触发告警」。核心思路是:只读取元数据 + 本地离线比对 + 避开密码字段明文暴露。
为什么不能直接用 mysql_login 或 hydra
这些工具本质是模拟登录,会留下大量失败连接记录,触发安全设备的暴力破解告警;在生产库上可能被 WAF、IDS 或数据库审计模块拦截,甚至导致连接池耗尽。某次真实事件中,运维误在核心 MySQL 上跑了一次 mysql-brute,结果 3 分钟内被自动封禁了源 IP,业务登录接口全挂。
- 所有爆破类操作(
msfconsole use auxiliary/scanner/mysql/mysql_login、hydra -t 4 -L users.txt -P pass.txt mysql://host)一律禁止在生产环境执行 - 即使加了
-t 1限速,TCP 连接建立/断开本身就会被 netflow 或ss -tnp | grep :3306捕获 - MySQL 8.0+ 默认关闭
old_passwords,但mysql_login模块对caching_sha2_password握手支持不稳定,容易漏报
SELECT User, Host, authentication_string FROM mysql.user 能看出什么
这条语句是唯一允许在生产库上安全执行的起点。重点不是看密码哈希值本身,而是看三类高危信号:
-
authentication_string为空('')或为*0(表示空密码哈希),说明是空口令账号 -
User = ''(匿名用户),Host 为'%'或'192.168.%',属于默认拒绝范围但常被忽略 - Host 为
'%'且 User 是root、admin、sa等特权名,哪怕哈希看起来“随机”,也应优先人工复核
注意:authentication_string 字段内容是哈希值(如 $A$...xxx 或 *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9),不能直接拿去爆破——但可以导出后离线分析其算法强度(比如是否还是 mysql_native_password + MD5)。
如何离线判断哈希是否对应弱口令
把导出的 authentication_string 值拷到隔离机,用 Python 快速验证:
python3 -c "
import hashlib, sys
h = sys.argv[1]
if h.startswith('*') and len(h) == 41:
# classic mysql_native_password: SHA1(sha1(pass))
p = '123456'.encode()
h_test = '*' + hashlib.sha1(hashlib.sha1(p).digest()).hexdigest().upper()
print('likely weak' if h == h_test else 'not trivially weak')
"更稳妥的做法是用 zxcvbn 对常见默认密码(root、password、mysql、123456、admin123)批量哈希比对,而不是穷举。MySQL 5.7+ 的 validate_password 插件若已启用,还可查 SHOW VARIABLES LIKE 'validate_password%'; 看策略是否生效——但该变量本身不反映历史账号是否符合策略。
检查时最容易被跳过的两个盲点
一是 mysql.db 表里可能存着被授权给低权限用户的高危库权限,比如 test.* 库被授予了 FILE 权限,配合弱口令就能写 Webshell;二是 information_schema.PLUGINS 中若存在非官方插件(如 lib_mysqludf_sys),说明已有攻击者提权成功,此时弱口令只是表象,根因已是失陷。
真正要盯住的,从来不是「密码够不够长」,而是「这个账号有没有存在的必要」——删掉 test 用户、禁用 root@'%'、把所有 Host = '%' 改成具体内网段,比给每个账号换一遍密码管用得多。


















