文章总结: MySQL8.4中存在一个蜜罐防御机制,当尝试使用不存在的用户登录时,系统会创建影子用户并随机分配认证插件。若分配到已默认禁用的mysql_native_password插件,会触发插件未加载错误而非常规的访问拒绝错误。这种设计旨在防止攻击者通过错误信息判断真实用户的存在。为避免此问题,可手动启用插件或创建兜底用户。这是MySQL在安全与兼容性之间权衡的结果,体现了数据库对抗暴力破解的精妙设计。
综合评分: 91
文章分类: 漏洞分析,数据库安全,安全建设,安全运营,WEB安全
一个不存在的用户,竟让MySQL 8.4当场崩溃?背后藏着甲骨文不敢明说的安全暗战!
原创
小柳实验室
小柳实验室
2025年11月25日 06:30
湖南
一个看似简单的登录错误,背后竟藏着 MySQL 防御黑客的精妙设计
最近在测试 MySQL 8.4 新实例时,遇到一个令人困惑的现象:用不存在的用户 u2 登录时,报错 Plugin 'mysql_native_password' is not loaded;而用另一个不存在的用户 u1 登录,却返回常规的 Access denied 错误。更诡异的是,检查用户表发现根本没有用户使用mysql_native_password 插件!
# 用 u2 登录(用户不存在)
$ mysql -h127.0.0.1 -P3316 -uu2 -p123
ERROR 1524 (HY000): Plugin 'mysql_native_password' is not loaded
# 用 u1 登录(用户同样不存在)
$ mysql -h127.0.0.1 -P3316 -uu1 -p123
ERROR 1045 (28000): Access denied for user 'u1'@'127.0.0.1'
查看用户认证插件,清一色都是 caching_sha2_password:
mysql> SELECT host, user, plugin FROM mysql.user;
+-----------+------------------+-----------------------+
| host | user | plugin |
+-----------+------------------+-----------------------+
| % | root | caching_sha2_password |
| localhost | mysql.infoschema | caching_sha2_password |
| ...(其他系统用户)... | caching_sha2_password |
+-----------+------------------+-----------------------+
灵魂拷问:
同样不存在的用户,为何报错天差地别?
从未启用的 mysql_native_password,为何突然“背锅”?
🔍 深度解密:MySQL 的“蜜罐”防御机制
当黑客尝试暴力破解数据库时,最怕什么?—— 通过错误信息判断哪些用户名真实存在。
MySQL 早在多年前就布下“暗棋”:对不存在的用户,绝不直接暴露“用户不存在”!而是精心设计了一套 “蜜罐用户” 机制:
步骤一:客户端发起连接
当 u2 尝试登录,服务端收到请求后,按流程启动认证。
步骤二:服务端“伪装”用户身份
关键代码藏在 find_mpvio_user() 函数中:
→ 若用户不存在,不返回错误,而是调用 decoy_user() 生成一个“影子用户”;
→ 随机分配一个认证插件(如 caching_sha2_password、sha256_password或 mysql_native_password);
→ 用这个假身份继续认证流程,让攻击者无法分辨真假。
// MySQL 源码片段:随机分配插件给“影子用户”
const LEX_CSTRING Cached_authentication_plugins::cached_plugins_names[] = {
{STRING_WITH_LEN("caching_sha2_password")}, // 概率1/3
{STRING_WITH_LEN("mysql_native_password")}, // 概率1/3 ← 问题根源!
{STRING_WITH_LEN("sha256_password")} // 概率1/3
};
// 根据用户名+IP生成唯一Key,确保同客户端每次“待遇”一致
uint plugin_num = random_number % PLUGIN_LAST;
user->plugin = cached_plugins_names[plugin_num];
步骤三:二次认证触发“插件陷阱”
若客户端自带的插件(如新版客户端默认用caching_sha2_password)与“影子用户”分配的插件不一致,MySQL 会发起二次认证; 当分配到mysql_native_password时(如 u2 的遭遇),服务端尝试加载该插件; 但在MySQL 8.4中,该插件默认已禁用! 于是触发致命错误:ERROR 1524 (HY000): Plugin ‘xxx’ is not loaded而 u1 幸运地分配到了caching_sha2_password,走完认证流程后,只返回常规的Access denied` —— 完美隐藏了“用户不存在”的事实。
💡 核心结论:安全与兼容的艰难平衡
报错差异的本质
→ u2 触发插件错误:因随机分配到了已废弃的 mysql_native_password;
→ u1 返回访问拒绝:因分配到当前启用的插件,完成完整认证流程。
为何提示“未加载插件”
MySQL 8.4 彻底移除了 default_authentication_plugin 参数,并将caching_sha2_password 作为唯一默认插件。为精简架构,mysql_native_password 默认不再加载(除非手动启用),但“蜜罐机制”仍会随机分配它。
⚠️ 运维启示:如何避免踩坑?
| 场景 | 解决方案 |
| — | — |
| 需兼容旧版客户端 | 手动启用插件: INSTALL PLUGIN mysql_native_password SONAME 'auth_socket.so'; |
| 彻底消除该报错 | 创建“兜底用户”: CREATE USER 'fake_user'@'%' IDENTIFIED WITH caching_sha2_password BY 'dummy'; (使随机分配时总有可用插件) |
| 诊断真实用户问题 | 先检查用户是否存在 ! 避免被蜜罐机制干扰判断 |
安全设计的哲学:这个看似“反直觉”的机制,正是
MySQL对抗暴力破解的盾牌。它用技术复杂性换取了安全性——当黑客看到千奇百怪的报错时,将无法区分哪些是真实账户。在安全与易用之间,数据库守护者们始终在走钢丝。
技术没有银弹,只有权衡的艺术。
下一次当你看到“插件未加载”的报错,不妨会心一笑:这不是 Bug,而是一场静默的安全攻防战。
(注:本文基于 MySQL 8.4.0 源码分析,其他版本行为可能不同)
🔖标签:#MySQL8.4 #数据库安全 #DBA日常 #源码级解析 #运维避坑
📬 关注我
推荐阅读
Docker磁盘空间告急?3分钟教你彻底清理,释放大量空间!
【实战】打造超强Linux防火墙!10分钟提升服务器安全等级
划时代AI助手来袭!蚂蚁集团「灵光」:不止会聊天,更会创造全模态内容!
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:小柳实验室 小柳实验室《一个不存在的用户,竟让MySQL 8.4当场崩溃?背后藏着甲骨文不敢明说的安全暗战!》