MySQL 安全最佳实践

MySQLMySQLBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在本次实验中,我们将专注于增强你的 MySQL 数据库的安全性。本实验涵盖了重要的安全最佳实践,包括更改 root 用户密码、启用 SSL 以实现安全连接、撤销用户的多余权限以及删除匿名用户账户。

第一步是通过 sudo mysql -u root 以 root 用户身份访问 MySQL shell,然后使用 ALTER USER 语句将 root 密码更新为一个强而唯一的密码。更新密码后,我们将使用 FLUSH PRIVILEGES; 刷新权限,以确保更改立即生效。最后,我们将退出 MySQL shell 并测试新密码。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL mysql(("MySQL")) -.-> mysql/BasicKeywordsandStatementsGroup(["Basic Keywords and Statements"]) mysql(("MySQL")) -.-> mysql/DatabaseFunctionsandDataTypesGroup(["Database Functions and Data Types"]) mysql(("MySQL")) -.-> mysql/TransactionManagementandSecurityGroup(["Transaction Management and Security"]) mysql(("MySQL")) -.-> mysql/SystemManagementToolsGroup(["System Management Tools"]) mysql/BasicKeywordsandStatementsGroup -.-> mysql/alter_table("Table Modification") mysql/BasicKeywordsandStatementsGroup -.-> mysql/select("Data Retrieval") mysql/BasicKeywordsandStatementsGroup -.-> mysql/delete("Data Deletion") mysql/DatabaseFunctionsandDataTypesGroup -.-> mysql/user("User Info Function") mysql/TransactionManagementandSecurityGroup -.-> mysql/identified_by("User Authentication") mysql/TransactionManagementandSecurityGroup -.-> mysql/grant_permission("Permission Granting") mysql/TransactionManagementandSecurityGroup -.-> mysql/revoke_permission("Permission Revocation") mysql/SystemManagementToolsGroup -.-> mysql/show_status("Status Overview") subgraph Lab Skills mysql/alter_table -.-> lab-550914{{"MySQL 安全最佳实践"}} mysql/select -.-> lab-550914{{"MySQL 安全最佳实践"}} mysql/delete -.-> lab-550914{{"MySQL 安全最佳实践"}} mysql/user -.-> lab-550914{{"MySQL 安全最佳实践"}} mysql/identified_by -.-> lab-550914{{"MySQL 安全最佳实践"}} mysql/grant_permission -.-> lab-550914{{"MySQL 安全最佳实践"}} mysql/revoke_permission -.-> lab-550914{{"MySQL 安全最佳实践"}} mysql/show_status -.-> lab-550914{{"MySQL 安全最佳实践"}} end

更改 root 用户密码

在这一步中,我们将专注于更改 MySQL 中的 root 用户密码。这是一项至关重要的安全措施,可防止未经授权的用户访问你的数据库。root 用户拥有最高权限,因此保持其密码的强度和安全性至关重要。

首先,让我们以 root 用户身份访问 MySQL shell。由于我们是在 LabEx 虚拟机(VM)中操作,所以将使用 sudo 命令以 root 用户身份执行命令。

在 LabEx 虚拟机中打开你的终端。默认目录是 ~/project

要以 root 用户身份访问 MySQL shell,请执行以下命令:

sudo mysql -u root

你可能会被要求输入 labex 用户的密码。由于 labex 用户具有无密码的 sudo 权限,只需按 Enter 键即可。

现在你已进入 MySQL shell。你会看到一个类似 mysql> 的提示符。

接下来,我们将更改 root 用户的密码。与旧版本(mysql_native_password)相比,MySQL 8.0 及更高版本使用了不同的认证插件(caching_sha2_password)。我们将使用 ALTER USER 语句来更新密码并确保兼容性。

执行以下 SQL 命令,将 your_new_password 替换为一个强而唯一的密码:

ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'your_new_password';

重要提示: 选择一个包含大写字母、小写字母、数字和符号的强密码。不要使用你在其他账户中使用过的密码。

执行命令后,你应该会看到以下输出:

Query OK, 0 rows affected (0.00 sec)

现在,让我们刷新权限以确保更改立即生效:

FLUSH PRIVILEGES;

你应该会看到以下输出:

Query OK, 0 rows affected (0.00 sec)

最后,通过输入以下命令退出 MySQL shell:

exit

你将返回到常规的终端提示符。

现在,让我们测试新密码。尝试使用新密码登录 MySQL shell:

mysql -u root -p

你将被要求输入密码。输入你设置的新密码。如果你成功登录,就说明你已成功更改了 root 用户的密码。

启用 SSL 以实现安全连接

在这一步中,我们将为你的 MySQL 服务器启用 SSL(安全套接层),以实现安全连接。SSL 会对客户端和服务器之间传输的数据进行加密,防止数据被窃听和篡改。

首先,我们需要生成 SSL 证书和密钥。我们将使用 openssl 命令行工具来完成此操作。

在 LabEx 虚拟机中打开你的终端。默认目录是 ~/project

我们将创建一个目录来存储 SSL 证书和密钥。执行以下命令:

mkdir ssl
cd ssl

现在,让我们生成服务器密钥:

sudo openssl genrsa 2048 > server-key.pem

接下来,生成证书签名请求(CSR):

sudo openssl req -new -key server-key.pem -out server-req.pem

你会被要求输入一些信息,如国家名称、州、城市、组织名称等。你可以输入合适的值,也可以留空。对于“通用名称”,输入 localhost 或服务器的主机名/IP 地址。

现在,对证书请求进行签名以创建 SSL 证书:

sudo openssl x509 -days 365 -in server-req.pem -signkey server-key.pem -out server-cert.pem

此命令会创建一个有效期为 365 天的自签名证书。

接下来,生成客户端密钥:

sudo openssl genrsa 2048 > client-key.pem

生成客户端证书签名请求(CSR):

sudo openssl req -new -key client-key.pem -out client-req.pem

你会被要求输入与服务器 CSR 类似的信息。

现在,对客户端证书请求进行签名:

sudo openssl x509 -days 365 -in client-req.pem -signkey client-key.pem -out client-cert.pem

最后,生成 CA(证书颁发机构)密钥和证书:

sudo openssl genrsa 2048 > ca-key.pem
sudo openssl req -new -x509 -days 365 -key ca-key.pem -out ca-cert.pem

现在,~/project/ssl 目录下有以下文件:

  • server-key.pem
  • server-cert.pem
  • client-key.pem
  • client-cert.pem
  • ca-key.pem
  • ca-cert.pem

接下来,我们需要配置 MySQL 以使用这些 SSL 证书。

编辑 MySQL 配置文件。其位置可能因 MySQL 安装方式而异,但通常位于 /etc/mysql/my.cnf/etc/my.cnf。由于我们是在 Docker 容器中,我们将在 ~/project 目录下创建一个 my.cnf 文件,并将其挂载到容器中。

~/project 目录下创建一个名为 my.cnf 的文件:

cd ~/project
nano my.cnf

my.cnf 文件中添加以下内容:

[mysqld]
ssl-cert=/var/lib/mysql/ssl/server-cert.pem
ssl-key=/var/lib/mysql/ssl/server-key.pem
ssl-ca=/var/lib/mysql/ssl/ca-cert.pem
require_secure_transport=ON

重要提示: my.cnf 文件中的路径是相对于 MySQL 容器的。我们需要将证书复制到容器内的正确位置。由于我们无法直接访问容器的文件系统,在本次实验中我们将跳过此步骤。require_secure_transport=ON 设置会强制所有连接使用 SSL。

现在,让我们重启 MySQL 服务器。由于我们不能使用 systemctl,在本次实验中我们将跳过重启步骤。在实际场景中,你需要重启 MySQL 服务器以使更改生效。

最后,让我们使用 SSL 连接到 MySQL 服务器。

mysql --ssl-ca=~/project/ssl/ca-cert.pem --ssl-cert=~/project/ssl/client-cert.pem --ssl-key=~/project/ssl/client-key.pem -u root -p

当提示输入密码时,输入 root 密码。

要验证连接是否使用了 SSL,请执行以下 SQL 命令:

SHOW STATUS LIKE 'Ssl_cipher';

如果 Value 列显示了一个密码套件,那么连接正在使用 SSL。

+---------------+-----------------------+
| Variable_name | Value                 |
+---------------+-----------------------+
| Ssl_cipher    | TLS_AES_256_GCM_SHA384 |
+---------------+-----------------------+
1 row in set (0.00 sec)

如果 Value 列为空,那么连接没有使用 SSL。

+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Ssl_cipher    |       |
+---------------+-------+
1 row in set (0.00 sec)

撤销用户的多余权限

在这一步中,我们将专注于撤销 MySQL 用户的多余权限。这是一项至关重要的安全措施,可在用户账户被盗用时减少潜在损失。我们将创建一个用户,为其授予一些权限,然后撤销其中部分权限。

首先,让我们以 root 用户身份访问 MySQL shell。

在 LabEx 虚拟机中打开你的终端。默认目录是 ~/project

要以 root 用户身份访问 MySQL shell,请执行以下命令:

sudo mysql -u root

你可能会被要求输入 labex 用户的密码。由于 labex 用户具有无密码的 sudo 权限,只需按 Enter 键即可。

现在你已进入 MySQL shell。你会看到一个类似 mysql> 的提示符。

让我们创建一个名为 testuser 的新用户,密码为 testpassword

CREATE USER 'testuser'@'localhost' IDENTIFIED BY 'testpassword';

你应该会看到以下输出:

Query OK, 0 rows affected (0.00 sec)

现在,让我们为 testuser 授予一些权限。例如,我们为其授予对名为 testdb 的数据库的 SELECTINSERTUPDATE 权限。如果该数据库不存在,我们将先创建它。

CREATE DATABASE IF NOT EXISTS testdb;
GRANT SELECT, INSERT, UPDATE ON testdb.* TO 'testuser'@'localhost';

你应该会看到以下输出:

Query OK, 0 rows affected (0.00 sec)

现在,假设我们要撤销 testuserUPDATE 权限。我们可以使用 REVOKE 语句。

REVOKE UPDATE ON testdb.* FROM 'testuser'@'localhost';

你应该会看到以下输出:

Query OK, 0 rows affected (0.00 sec)

现在,让我们刷新权限以确保更改立即生效:

FLUSH PRIVILEGES;

你应该会看到以下输出:

Query OK, 0 rows affected (0.00 sec)

要验证 testuser 的权限,你可以使用 SHOW GRANTS 语句:

SHOW GRANTS FOR 'testuser'@'localhost';

输出将显示授予 testuser 的权限。你应该会看到 SELECTINSERT 权限,但没有 UPDATE 权限。

+---------------------------------------------------------------------------------------------------------------------------------------+
| Grants for testuser@localhost                                                                                                       |
+---------------------------------------------------------------------------------------------------------------------------------------+
| GRANT SELECT, INSERT ON `testdb`.* TO `testuser`@`localhost`                                                                        |
| GRANT USAGE ON *.* TO `testuser`@`localhost`                                                                                           |
+---------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

最后,通过输入以下命令退出 MySQL shell:

exit

你将返回到常规的终端提示符。

删除匿名用户账户

在这一步中,我们将从你的 MySQL 服务器中删除匿名用户账户。匿名用户账户是指用户名是空字符串('')的账户,它们可能会导致数据库被未经授权访问。删除这些账户是一项良好的安全措施。

首先,让我们以 root 用户身份访问 MySQL shell。

在 LabEx 虚拟机中打开你的终端。默认目录是 ~/project

要以 root 用户身份访问 MySQL shell,请执行以下命令:

sudo mysql -u root

你可能会被要求输入 labex 用户的密码。由于 labex 用户具有无密码的 sudo 权限,只需按 Enter 键即可。

现在你已进入 MySQL shell。你会看到一个类似 mysql> 的提示符。

为了识别匿名用户账户,我们可以查询 mysql.user 表。

SELECT User, Host FROM mysql.user WHERE User='';

这个查询将显示所有用户名为空的用户。Host 列表示用户可以从哪个主机进行连接。你可能会看到类似 ''@'localhost'''@'%' 的条目。

要删除匿名用户账户,请使用 DROP USER 语句。例如,要删除可以从 localhost 连接的匿名用户账户,请执行以下命令:

DROP USER ''@'localhost';

你应该会看到以下输出:

Query OK, 0 rows affected (0.00 sec)

如果还有其他匿名用户账户(例如 ''@'%'),也将它们删除:

DROP USER ''@'%';

你应该会看到以下输出:

Query OK, 0 rows affected (0.00 sec)

删除匿名用户账户后,刷新权限以确保更改立即生效:

FLUSH PRIVILEGES;

你应该会看到以下输出:

Query OK, 0 rows affected (0.00 sec)

要验证匿名用户账户是否已被删除,请再次运行 SELECT 查询:

SELECT User, Host FROM mysql.user WHERE User='';

这次,查询应该返回一个空结果集。

最后,通过输入以下命令退出 MySQL shell:

exit

你将返回到常规的终端提示符。

总结

在本次实验中,第一步着重于通过更改 root 用户密码来增强 MySQL 的安全性。这需要使用 sudo mysql -u root 命令以 root 用户身份访问 MySQL shell。

此步骤的核心是执行 ALTER USER 语句来更新 root 用户的密码,以确保与 MySQL 8.0 及更高版本中使用的 caching_sha2_password 认证插件兼容。随后使用 FLUSH PRIVILEGES 命令立即应用更改,最后退出 MySQL shell。