• 浅谈 MySQL 新的身份验证插件 caching_sha2_password


    • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
    • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。

    介绍

    从 MySQL 8.0.4 开始,MySQL 默认身份验证插件从 mysql_native_password 改为 caching_sha2_password 。相应地,libmysqlclient 也使用 caching_sha2_password 作为默认的身份验证机制。

    起因

    在这之前 MySQL 5.6/5.7 使用的默认密码插件是 mysql_native_passwordmysql_native_password 的特点是不需要加密的连接。该插件验证速度特别快,但是不够安全,因为,mysql_native_password 使用的是于 SHA1 算法,NIST(美国国家标准与技术研究院)在很早之前就已建议停止使用 SHA1 算法,因为 SHA1 和其他哈希算法(例如 MD5)容易被破解。

    其实从 MySQL 5.6 开始就引入了更安全的认证机制:ha256_password 认证插件。它使用一个加盐密码(salted password)进行多轮 SHA256 哈希(数千轮哈希,暴力破解更难),以确保哈希值转换更安全。但是,建立安全连接和多轮 hash 加密很耗费时间。虽然安全性更高,但是验证速度不够快。

    改进

    MySQL 试图结合俩者的优点。于是在 MySQL-8.0.3 引入了一个新的身份验证插件 caching_sha2_password ,作为sha256_password的代替方案,在sha256_password 的基础上进行了改进补上了短板,既解决安全性问题又解决性能问题。与此同时 sha256_password将退出时代的浪潮。MySQL 预计在未来版本中将其删除。使用 sha256_password 进行身份验证的 MySQL 帐户建议转为 caching_sha2_password

    结果

    因为默认身份验证机制的更改,大家在使用 MySQL 8.0 时候出现了很多相关的问题。网上的大部分教程都是教人改回mysql_native_password验证方式 mysql_native_password。但是笔者认为,MySQL 更改默认插件是为了更好的安全性考虑。如果有 MySQL 服务要公网上使用,建议还是尽量使用 caching_sha2_password作为认证插件。

    示例:使用旧版本客户端连接时报错:

    shell> mysql -uroot -p
    ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded
    • 1

    具体机制分析

    mysql_native_password

    mysql_native_password 作为 MySQL 5.6/5.7 的默认密码插件 。其优点是它支持 challenge-response (挑战应答方式),这是非常快的验证机制,无需在网络中发送实际密码,并且不需要加密的连接。

    客户端连接MySQL实例时,首先需要从服务器端获得一个20字节的随机数。

    此外,mysql_native_password 使用了新的哈希算法进行认证校验。对于用户的原始密码,通过SHA1(SHA1(password))两次哈希计算结果保存在 mysql.user 表的 authentication_string 列中。其中用户密码通过哈希计算后保存,没有加盐(salt)。

    通过上述这样的处理,MySQL数据库本身已然非常安全。然而,随着时间的推移,目前存在以下两种潜在风险:

    • SHA1哈希算法也已经变得比较容易破解。
    • 相同的密码拥有相同的哈希值。

    SHA1、MD5等之前的哈希算法都已然不再安全,更为安全的SHA256、SHA512哈希算法也已推出。作为数据存储最终承载者,应该使用更新的加密机制机制。

    caching_sha2_password

    在cache_sha2_password密码认证机制下,其改进如下所示:

    • 保存在 authentication_string 中的哈希值为加盐后的值,即使两个不同用户的密码相同,保存在计算机中的哈希值也不同。
    • 哈希算法升级为了更为安全SHA256算法。
    • 哈希算法的 round 次数从原来的两次,提升为了5000次,round次数越多,每次计算哈希值的代价越大,破解难度也就越大。
    • 用TLS的加密或RSA密钥传输方式从客户端将密码传送到服务端。
    通讯过程解析
    1. 对于大多数连接尝试,当密码的哈希值有缓存在内存中时,它的验证是基于 SHA256 的challenge-response机制(与 mysql_native_password 中基于 SHA1 的challenge-response机制相比更快),下图演示了在有哈希缓存时的验证流程。

    file

    1. 客户端连接服务端
    2. 服务端给客户端发送 Nonce(20 字节长的随机数据)
    3. 客户端使用 XOR(SHA256(password), SHA256(SHA256(SHA256(password)), nonce)) 生成 Scramble 发送给服务端
    4. 服务端检查 username/SHA256(SHA256(user_password)) 是否在内存缓存条目中存在,存在则证明合法;发送 fast_auth_success 包到客户端
    5. 服务端发送 OK 包到客户端
    6. 进入命令阶段

    Nonce 是一个在加密通信只能使用一次的数字。在认证协议中,它往往是一个随机或伪随机数(salt),以避免暴力攻击。

    1. 当没有这种缓存时,caching_sha2_password 需要使用安全连接进行密码交换。考虑到用户更改和 FLUSH PRIVILEGES 操作频率比较低,所以在大多数情况下,使用的都是基于challenge-response的身份验证,不用建立安全连接。这省去了建立安全连接需要耗费的资源。下图总结了完整的验证流程。

    file

    1. 客户端连接服务端
    2. 服务端给客户端发送 Nonce(20 字节长的随机数据)
    3. 客户端使用 XOR(SHA256(password), SHA256(SHA256(SHA256(password)), nonce)) 生成 Scramble 发送给服务端
    4. 服务端检查 username/SHA256(SHA256(user_password)) 是否在内存缓存条目中存在,不存在则发送 perform_full_authentication 包到客户端继续认证
    5. 客户端收到 perform_full_authentication 包,可以进行如下处理
    6. 如果安全连接已经建立基于 ,则可以直接发送明文密码到服务端 向服务端发起获取公钥的请求(或者指定服务端公钥文件),使用公钥+Nonce加密密码,发送加密后的密码到服务端 服务器通过 SHA256 算法计算得到哈希值,判断是否用户认证通过,通过则发送 OK 包到客户端
    7. 进入命令阶段

    这里详细解释一下 RSA 非对称加密的通信过程:

    首先先明确一个概念:非对称加密算法中,有两个密钥:公钥和私钥。如果用公钥进行加密,只有对应的私钥才能解密;反之亦然。

    RSA 密钥交换过程:

    服务器生成一对密钥并将公钥向其他方公开(明文发送给客户端);

    客户端使用服务器的公钥对密码进行加密后发送给服务器;

    服务器用对应的私钥对加密信息进行解密。

    因为客户端用公钥加密的信息只能用服务器的私钥解密,所以这个连接过程可以视为加密通信。

    file

    需要注意的地方

    默认身份验证插件的更改意味着:

    在 MySQL 8.0.4 之后创建的所有新用户将默认使用 caching_sha2_password 作为身份验证插件。

    mysql> SELECT USER,PLUGIN FROM mysql.`user` ;
    +------------------+-----------------------+
    | USER             | PLUGIN                |
    +------------------+-----------------------+
    | root             | caching_sha2_password |
    | mysql.infoschema | caching_sha2_password |
    | mysql.session    | caching_sha2_password |
    | mysql.sys        | caching_sha2_password |
    +------------------+-----------------------+
    6 rows in set (0.06 sec)
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    libmysqlclient 默认使用 caching_sha2_password,可以通过手动修改切换到其他的身份验证插件。

    对于使用 caching_sha2_password 插件的客户端,连接到服务器时,密码不会暴露为明文。密码传输是如何进行的取决于是否使用安全连接或 RSA 对密码加密:

    • 如果连接是安全的,可以不使用 RSA 密钥。适用于使用 TLS 加密的 TCP 连接,以及 Unix 套接字文件和共享内存连接。密码以明文格式发送,但不能被窃听,因为连接是安全的。
    • 如果连接不是安全的,可以使用 RSA 密钥对。适用于未使用 TLS 加密的 TCP 连接和 named-pipe 连接。RSA 仅用于客户端和服务器之间的密码交换,防止密码被截取。当服务器接收到使用公钥加密的密码后,它使用私钥解密。一个随机字符串用在加密中,防止重放攻击(repeat attacks)。

    在 MySQL 8.0.3 以上版本中。默认自动完成 RSA 密钥对进行密码交换。

    关于主从复制

    复制本身是支持加密的连接。在 MySQL 8.0.4中,添加了复制对 RSA 加密的支持。

    如果用于复制的用户使用了 caching_sha2_password身份验证插件,并且没有启用安全连接( 在group_replication_recovery 启用SSL支持),MySQL 将使用 RSA 密钥对进行密码的交换,可以把主节点的公钥手动拷贝到从节点的服务器中,也可以设置成:自动为请求加入组的节点提供公钥。

    • CHANGE MASTER 可以通过以下俩个参数来启用基于 caching_sha2_password RSA 密钥来交换密码:

        指定 RSA 公钥路径
       - MASTER_PUBLIC_KEY_PATH ="key_file_path"  
      
        #从服务端获取 RSA 公钥
       - GET_MASTER_PUBLIC_KEY = {0 | 1}
      • 1
      • 2
      • 3
      • 4
    • Group Replication 可以通过以下俩个参数来启用基于 caching_sha2_password RSA 密钥来交换密码:

       #指定 RSA 公钥路径
       ––group-replication-recovery-public-key-path
       #从服务端获取 RSA 公钥
      ––group-replication-recovery-get-public-key
      • 1
      • 2
      • 3

    数据库升级

    数据库升级到 MySQL 8.0.4 会怎样?

    在升级之前创建的用户,身份认证插件不会更改。在升级之后创建的用户默认使用 aching_sha2_password身份验证插件。除非使用 --default-authentication-plugin 手动指定认证插件插件。因为不会更改升级前已有用户。因此,使用升级后依然可以用旧版本的客户端连接这些用户。

    相应地,libmysqlclient 支持 mysql_options() C API函数的 MYSQL_DEFAULT_AUTH 选项。(对于 MySQL 包中可用的基于 libmysqlclient 的客户端工具,可以用 ––default-auth 命令行选项达到相同的目的。)

    建议使用 cache_sha2_password 因为它更安全。并且升级 libmysqlclient 到 MySQL 8.0.4 或更高版本,以便支持新的身份验证插件。

    参考资料

    MySQL 8.0.4 : New Default Authentication Plugin : caching_sha2_password

    得物技术浅谈MySQL 8.0:新的身份验证插件

    MySQL 8.0密码认证机制升级,不知道可能导致业务不可用!!! 组复制安装部署 | 全方位认识 MySQL 8.0 Group Replication


    Enjoy GreatSQL :)

    关于 GreatSQL

    GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。

    相关链接: GreatSQL社区 Gitee GitHub Bilibili

    GreatSQL社区:

    捉虫活动详情:https://greatsql.cn/thread-97-1-1.html

    社区博客有奖征稿详情:https://greatsql.cn/thread-100-1-1.html

    6440

    技术交流群:

    微信:扫码添加GreatSQL社区助手微信好友,发送验证信息加群

    image-20221030163217640)

  • 相关阅读:
    PHP redis string
    我为什么要使用GPT????
    【Unity ShaderGraph】| 物体靠近时局部溶解,根据坐标控制溶解的位置【文末送书】
    数据库系列:InnoDB下实现高并发控制
    苹果跌落全球市值第一宝座;联想一员工侵占公司工时费近1000万;PHP 8.1.6 发布|极客头条
    Elasticsearch
    tinymce输入框怎么限制只输入空格或者回车时不能提交
    【虚拟机】VMWare的NAT静态IP设置
    【杂项】如何将指定字体装入电脑然后能在Office软件里使用该字体?
    leetcode 4405.统计子矩阵
  • 原文地址:https://blog.csdn.net/GreatSQL2021/article/details/127647735