内容一:数据库运行环境安全
1.1 保证运行数据库的系统是安全的
(步骤略)
1.2 以最小权限用户运行数据库
1.2.1 停止数据库
# systemctl stop mariadb
(补充:这里以停止 MariaDB 数据库为例)
1.2.2 修改数据库目录的
# chown -R mysql /var/lib/mysql
(补充:MariaDB&MySQL 数据库数据默认存放位置是 /var/lib/mysql)
1.2.3 修改配置文件
# vim /etc/my.cnf
在:
......
[mysqld]
下面添加:
user=mysql
......
(补充:这里以 MariaDB 数据库的配置文件是 /etc/my.cnf 为例)
1.2.4 启动数据库
# systemctl start mariadb
(补充:这里以启动 MariaDB 数据库为例)
1.3 将数据库版本升级到更新的版本
(步骤略)
内容二:数据库库安全
2.1 删除所有不用的库
2.1.1 查看所有库的列表
> show databases;
2.1.2 删除测试库
> drop database <database>
2.2 删除所有测试库
2.2.1 方法一:手动删除所有测试库
2.2.1.1 查看所有库的列表
> show databases;
2.2.1.2 删除测试库
> drop database <database>
2.2.2 方法二:使用工具删除所有测试库
# sudo mysql_secure_installation
2.3 禁用客户端本地数据被读取
2.3.1 修改配置文件
# vim /etc/my.cnf
在:
......
[mysqld]
下面添加:
local-infile=0
......
(补充:这里以 MariaDB 数据库的配置文件是 /etc/my.cnf 为例)
(注意:此参数对 MariaDB 数据库无效)
2.3.2 重启数据库
# systemctl restart mariadb
(补充:这里以重启 MariaDB 数据库为例)
2.4 保护数据的本地存储
思路如下:
1) 使用加密的文件系统存储存放数据库的数据文件
2) 使用数据库之外的存储加密产品
3) 使用其他加密产品实现适当的数据保护
内容三:数据库登录安全
3.1 限制数据的导入导出
3.1.1 案例一:禁止数据的导入导出
3.1.1.1 修改配置文件
# vim /etc/my.cnf
在:
......
[mysqld]
下面添加:
secure_file_priv=null
......
(补充:这里以 MariaDB 数据库的配置文件是 /etc/my.cnf 为例)
(注意:此参数对 MariaDB 数据库无效)
3.1.1.2 重启数据库
# systemctl restart mariadb
(补充:这里以重启 MariaDB 数据库为例)
3.1.2 案例二:只允许将数据从 /root 目录导入或导出到 /root 目录
3.1.2.1 修改配置文件
# vim /etc/my.cnf
在:
......
[mysqld]
下面添加:
secure_file_priv=/root/
......
(补充:这里以 MariaDB 数据库的配置文件是 /etc/my.cnf 为例)
(注意:此参数对 MariaDB 数据库无效)
3.1.2.2 重启数据库
# systemctl restart mariadb
(补充:这里以重启 MariaDB 数据库为例)
3.1.3 案例三:不对数据作出导入和导出的限制
3.1.3.1 修改配置文件
# vim /etc/my.cnf
删除以下内容:
......
secure_file_priv=*
......
(补充:这里以 MariaDB 数据库的配置文件是 /etc/my.cnf 为例)
(注意:此参数对 MariaDB 数据库无效)
3.1.3.2 重启数据库
# systemctl restart mariadb
(补充:这里以重启 MariaDB 数据库为例)
3.2 删除无用和不需要的用户
3.2.1 查看所有用户
> select user,host from mysql.user;
3.2.2 删除不需要的用户
3.2.2.1 方法一:使用 drop 命令删除用户
> drop <user>;
3.2.2.2 方法二:使用 delete 命令删除用户
> delete from mysql.user where user='<user>' and host='<host>';
3.3 强制用户使用强密码
3.3.1 修改配置文件
# vim /etc/my.cnf
在:
......
[mysqld]
下面添加:
plugin-load=validate_password.so
......
(补充:这里以 MariaDB 数据库的配置文件是 /etc/my.cnf 为例)
3.3.2 重启数据库
# systemctl restart mariadb
(补充:这里以重启 MariaDB 数据库为例)
3.3.3 确保 validate_password_policy 被设置的参数是 MEDIUM
3.3.3.1 进入数据库
# mysql -p
3.3.3.2 查看 validate_password_policy 参数
> show variables like 'validate_password_policy';
+--------------------------+--------+
| Variable_name | Value |
+--------------------------+--------+
| validate_password.policy | MEDIUM |
| validate_password_policy | MEDIUM |
+--------------------------+--------+
2 rows in set (0.01 sec)
(补充:MEDIUM 的含义是密码最小的长度是 8 ,并且必须要有一个特殊字符和一个数字)
3.4 设置用户密码有效期
3.4.1 对于 MariaDB 和 MySQL 5.7 及以下的版本无法设置有效期,只能定期修改密码
> alter user 'root'@'localhost' identified by '<password>';
3.4.2 设置用户默认有效期的方法
3.4.2.1 修改用户密码默认的自动过期时间
> set global default_password_lifetime=<number>;
(补充:这里的数字代表天数)
3.4.2.2 让用户密码立刻过期
> aleter user '<user>'@'<host>' password expire;
3.4.2.3 让用户密码永不过期
> aleter user '<user>'@'<host>' password expire never;
(补充:建议普通用户每 90 天修改一次密码,敏感用户每 30 天修改一次密码,服务用户每 365 天修改一次密码)
3.5 删除无密码用户
3.5.1 方法一:手动删除无密码用户
3.5.1.1 查看无密码用户
3.5.1.1.1 MariaDB 和 MySQL 5.7 及以下版本查看无密码用户的方法
> select user, host, password from mysql.user;
3.5.1.1.2 MySQL 8.0 及以上版本查看无密码用户的方法
> select user, host, authentication_string from mysql.user;
3.5.1.2 手动删除不需要的用户的方法
3.5.1.2.1 手动删除用户的第一种方法:使用 drop 命令删除用户
> drop user <user>;
3.5.1.2.2 手动删除用户的第二种方法:使用 delete 命令删除用户
> delete from mysql.user where user='<user>' and host='<host>';
3.5.2 方法二:使用工具删除无密码用户
# sudo mysql_secure_installation
3.6 禁止非 root 用户 拥有 mysql.user 表访问权限
> show grants for root@localhost \G;
> select * from mysql.user where user='test' \G;
3.7 让用户只拥有最小但够用的权限
3.7.1 查看所有用户
> select user,host from mysql.user;
3.7.2 数据库权限层级
1) 全局层级权限:是指整个数据库级别的权限,存储在 mysql.user 表中
格式:
> grant all on *.* ......
> show grants for <user>;
> select * from mysql.user where user='<user>'\G;
2) 库级层级权限:是指数据库中某个库的权限,存储在 mysql.db 和 mysql.host 表中
格式:
> grant all on <database>.* ......
> show grants for <user>;
> select * from mysql.db where user='<user>'\G;
3) 表级层级权限:是指数据库中某个库的某个表的权限,存储在 mysql.tables_priv 表中
格式:
> grant all on <database>.<table> ......
> show grants for <user>;
> select * from mysql.tables_priv where user='<user>'\G;
4) 列级层级权限:是指数据库中某个库的某个表的某一单列的权限,存储在 mysql.columns_priv 表中
格式:
> grant select(<field>,<field>) on <database>.<table> ......
> show grants for <user>;
> select * from mysql.columns_priv where user='<user>'\G;
5) 子程序层级权限:适用于已存储的子程序
create routing, alter routing, execute 和 grant 权限适用于已存储的子程序
create routing, alter routing, execute 和 grant 权限可以被授予为全局层级和数据库层级
alter routing, execute 和 grant 权限可以被授予为子程序层级,并存储在 mysql.procs_priv 表中
格式:
> grant execute on <subroutine> <database>.<table> ......
> show grants for <user>;
> select * from mysql.procs_priv where user='<user>'\G;
3.7.3 查看每一个用户的权限
> show grants for '<user>'@'<host>';
3.7.4 删除用户多余的权限
如果有全局权限(如: FILE,PROCESS,SUPER, or SHUTDOWN 等权限),就删除这些权限
格式:
> revoke <privilege> on *.* from <user>@<host>;
> flush privileages;
内容四:数据库网络安全
4.1 禁止或者限制远程登录
(步骤略)
(
补充:
查看可以远程登录的用户的案例
> select user, host from mysql.user where host not in ('::1','127.0.0.1','localhost');
)
4.1.1 禁止远程登录
4.1.1.1 通过 MariaDB & MySQL 的配置文件禁止远程登录
4.1.1.1.1 修改配置文件
# vim /etc/my.cnf
在:
......
[mysqld]
下面添加:
skip-networking
bind-address=127.0.0.1
......
(补充:这里以 MariaDB 数据库的配置文件是 /etc/my.cnf 为例)
(注意:加入 skip-networking 这一行会让 MariaDB&MySQL 不再使用和监听任何端口)
4.1.1.1.2 重启数据库
# systemctl restart mariadb
(补充:这里以重启 MariaDB 数据库为例)
4.1.1.2 通过防火墙禁止远程登录
4.1.2 如果非要进行远程登录则要限制远程登录
4.1.2.1 限制访问数据库 TCP 端口的具体 IP 地址
(步骤略)
(补充:MariaDB&MySQL 数据库的默认端口号是 3306)
4.1.2.2 禁止有较大权限的用户被远程登录
1) 有 grant option 权限的用户
2) 被给予了全局权限像是 grant all on . 权限的用户
3) 一个可以访问 mysql.user 表的用户
4.2 对网络数据进行加密传输
4.2.1 生成 SSL
4.2.1.1 创建 CA 证书
# openssl genrsa 2048 > ca-key.pem
Generating RSA private key, 2048 bit long modulus
..+++
...................................+++
e is 65537 (0x10001)
# openssl req -new -x509 -nodes -days 3600 -key ca-key.pem -out ca.pem
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:ca
Email Address []:
(注意:创建 CA 证书、服务端证书、客户端证书时 Common Name 必须要有值,且必须相互不一样)
4.2.1.2 创建服务端证书,并去除加密,并使用刚刚的 CA 证书进行签名
# openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem -out server-req.pem
Generating a 2048 bit RSA private key
.............+++
...+++
writing new private key to 'server-key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
# openssl rsa -in server-key.pem -out server-key.pem
writing RSA key
# openssl x509 -req -in server-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem
Signature ok
subject=/C=XX/L=Default City/O=Default Company Ltd
Getting CA Private Key
(注意:创建 CA 证书、服务端证书、客户端证书时 Common Name 必须要有值,且必须相互不一样)
4.2.1.3 创建客户端证书,并去除加密,并使用刚刚的 CA 证书进行签名
# openssl req -newkey rsa:2048 -days 3600 -nodes -keyout client-key.pem -out client-req.pem
Generating a 2048 bit RSA private key
..................+++
..............................................+++
writing new private key to 'client-key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
# openssl rsa -in client-key.pem -out client-key.pem
writing RSA key
# openssl x509 -req -in client-req.pem -days 3600 -CA ca.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem
Signature ok
subject=/C=XX/L=Default City/O=Default Company Ltd
Getting CA Private Key
4.2.1.4 对生成的证书进行验证
# openssl verify -CAfile ca.pem server-cert.pem client-cert.pem
server-cert.pem: OK
client-cert.pem: OK
4.2.2 将 SSL 添加到 MariaDB & MySQL
4.2.2.1 将 SSL 放在指定的位置
# mv ca.pem /home/mysql/sslconfig/ca.pem
# mv server-cert.pem /home/mysql/sslconfig/server-cert.pem
# mv server-key.pem /home/mysql/sslconfig/server-key.pem
4.2.2.2 修改配置文件
# vim /etc/my.cnf
在:
......
[mysqld]
下面添加:
ssl-ca=/home/mysql/sslconfig/ca.pem
ssl-cert=/home/mysql/sslconfig/server-cert.pem
ssl-key=/home/mysql/sslconfig/server-key.pem
......
(补充:这里以 MariaDB 数据库的配置文件是 /etc/my.cnf 为例)
4.2.3 重启数据库
# systemctl restart mariadb
(补充:这里以重启 MariaDB 数据库为例)
4.2.4 验证 SSL
4.2.4.1 查看 have_ssl 和 ssl 变量
> show variables like 'have_%ssl';
> show variables like '%ssl%';
(补充:如果它们的参数为 yes ,表示服务端已经开启 SSL)
4.2.4.2 查看 SSL 的状态
> show status like 'ssl_cipher'
(补充:如果出现 “SSL:Cipher in use is DHE-RSA-AES256-SHA“ 则表示客户端已经使用 SSL 连接了)
4.2.5 确保所有数据库用户使用 SSL
> grant usage on <database>.<table> to '<user>'@'<host>' reouter ssl;
4.2.6 用户通过 SSL 连接数据库的方法
> mysql -u <user> -p -h <host> --ssl-ca=/home/mysql/sslconfig/ca.pem
内容五:开启审计
5.1 开启审计
5.1.1 MariaDB 和 MySQL 5.7 及以下版本开启审计的方法
> set global log_warning=2;
5.1.2 MySQL 8.0 及以上版本开启审计的方法
> set global general_log = on;
> set global log_timestamps = SYSTEM;
5.2 查看 MariaDB & MySQL 日志
# find /I "Access denied for user" <logfile_name>.log
# grep -i 'Access denied for user' <logfile_name>.log
(补充:中止连接、失败连接、尝试连接都将被写进日志)