技术资讯

网站开发:MySQL安全优化

TIME:2018-09-30

一、数据库相关

1、 MySQL版本的选择

在正式生产环境中,建议使用5.6或以上系列的版本(5.7不建议,曾经用过这个版本,问题有点多)。

2、 运行用户与端口的配置

2.1、确保MySQL运行用户为一般用户

确保mysql用户登录shell为nologin

01
[root@localhost ~]# usermod -s /sbin/nologin mysql

对MySQL运行用户降权,以普通用户身份运行MySQL

01
02
03
04
05
06
[root@localhost ~]# vim /usr/local/mysql/my.cnf
user = mysql
[root@localhost ~]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
[root@localhost ~]#

如果是用命令启动的,则在参数后面加上--user=mysql即可。

注意存放目录权限:

01
[root@localhost ~]# chown -R mysql.mysql /data/mysql/

按照以上操作后,mysql就会以用户mysql身份来启动mysqld,并且会以该用户身份来接受连接。以上mysql用户也可以改为其它用户。(不改变safe_mysqld是必要的。)

2.2、修改默认端口

建议修改默认端口3306,改为其他的一些端口。

01
02
03
04
05
06
07
[root@localhost ~]# vim /usr/local/mysql/my.cnf
[mysqld]
 port = 3389
[root@localhost ~]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
[root@localhost ~]#

3、 开启binlog

开启mysql二进制日志,在误删除数据的情况下,可以通过二进制日志恢复到某个时间点

3.1、登录MySQL查看bin-log状态

登录MySQL后,输入show variables like '%log_bin%';查看到binlog日志为OFF关闭状态;

image

3.2、开启binlog

先quit退出MySQL

wpsF6F6.tmp

修改MySQL配置文件my.cnf,加入如下两行

01
02
03
[root@localhost ~]# vim /usr/local/mysql/my.cnf
 server-id = 1
 log_bin =/data/mysql/mysql-bin

image

server-id标识着单个节点的id。在主从或者集群中会使用到,不能与其他节点相同。这里只有一台机,随机设置一个数字就好了。

第二行指定bin-log的名字与存储路径。

3.3、重启让配置生效

01
02
03
04
[root@localhost ~]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS!
Starting MySQL. SUCCESS!
[root@localhost ~]#

查看数据库日志目录:

注意:每次服务器(数据库)重启,服务器会调用flush logs;,新创建一个binlog日志

由于我之前重启过数据库,因此这里有mysql-bin.000001到mysql-bin.000003这三个文件。这里你们看到的应该只有mysql-bin.000001和mysql-bin.index两个文件

image

此时再次进入MySQL,查看binlog日志的状态。显示binlog日志为ON开启状态

image

到这里,binlog日志开启成功。

 

4、 用户认证和授权

4.1、删除匿名账号和空口令账号

登录MySQL,查看现在的账号情况

image

一般我们在数据库安装之后就会删除匿名账户如下:

01
mysql>delete from mysql.user where user='';

如上图所示,User这一栏里面都有值,没发现空的,所以没有匿名账户。这一步略过。

发现Password栏有三行空的,所以本机有空口令账号root。(危险)

我们为空口令账户设置密码

01
02
03
mysql>update mysql.user set password=password('$MYSQL_PASSWORD')where User="root" and Host="localhost";
mysql>update mysql.user set password=password('$MYSQL_PASSWORD')where User="root" and Host="127.0.0.1";
mysql>update mysql.user set password=password('$MYSQL_PASSWORD')where User="root" and Host="::1";

设置完毕后,再查看如下:

wpsF6FB.tmp

此时已经没有空口令和匿名账户了。

4.2、禁止root账户远程访问

Root权限太高,为了安全,一般我们禁止root账户从远程访问,root账户只允许从本地访问。

4.2.1、赋予localhost的root账户最高权限(以后维护用)。

查看localhost的root权限:

wpsF6FC.tmp

一般,localhost的root默认具有所有的权限,如上图(默认)。如果没有,则按照以下命令赋予最高权限:

01
02
mysql>grant all privileges on *.*to root@localhost identifiedby 'password' with grant option;
mysql> flush priveleges;

4.2.2、禁止root从远程访问,将主机为%并且用户为root行的删掉。

01
02
mysql>delete from mysql.user where User='root' and Host='%';
Query OK, 1 row affected (0.00 sec)

或者

01
02
mysql>update user set host ="localhost" where user ="root" and host ="%";
mysql> flushprivileges;

此时,你已经无法通过root账户进行远程访问数据库了。

除了root账户外,其他账户也应该严格控制,尽量不要放开远程访问,如果必须的话,应严格控制权限。根据业务需要,配置其需要的最小权限。

如果不需要,应禁止远程访问

禁止网络连接,防止猜解密码攻击、溢出攻击、和嗅探攻击。

注意: 仅限于应用和数据库在同一台主机的情况。

如果数据库不需要远程访问,可以禁止远程 TCP/IP 连接,通过在 MySQL 服务器的启动参数中添加--skip-networking参数使 MySQL 服务不监听任何 TCP/IP 连接,增加安全性。

4.3、建立普通账户并授权

Root账户已经无法远程进行访问了,但是我们很多业务是需要远程访问的,所以为业务新建一个普通账户,并赋予他们需要的最小权限。权限最小化原则。

4.3.1、创建用户

创建用户有三种方式:

方式一:(create命令创建用户)
01
02
mysql>create user 'test1'@'%' identifiedby '123';
Query OK, 0rows affected (0.08 sec)

如果用户已经存在会报错。

01
02
mysql>create user 'test1'@'%' identifiedby '123';
ERROR 1396 (HY000): OperationCREATE USER failedfor 'test1'@'%'

创建成功后,查看用户如下:

image

方式二:(insert命令插入用户,禁止使用此方式)
01
02
mysql>insert into mysql.user (Host,User,Password)Values('%','test2',PASSWORD('123'));
ERROR 1364 (HY000): Field'ssl_cipher' doesn't have adefault value

直接insert报错,因为mysql默认禁止直接insert添加用户。如果还是要改,可以修改配置文件:

01
02
[root@localhost doubles]# vim /usr/local/mysql/my.cnf
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

定位到上面这一行,这一行指定了mysql为严格模式,为了安全,严格模式是禁止使用insert形式创建mysql用户的,如果坚持还是要用,把配置修改为:

01
sql_mode=NO_ENGINE_SUBSTITUTION

然后重启服务

01
[root@localhost doubles]# /etc/init.d/mysqld restart

再次插入成功。

01
02
mysql>insert into mysql.user (Host,User,Password)Values('%','test2',PASSWORD('123'));
Query OK, 1 row affected, 3 warnings (0.00 sec)

改完配置再次插入成功。

image

方式三:(grant命令创建用户)
01
02
03
04
mysql>grant select on *.*to 'test3'@'%' identifiedby '123';
Query OK, 0rows affected (0.00 sec)
mysql> flushprivileges;
Query OK, 0rows affected (0.00 sec)

这种方式连同授权一起了。

image

查看权限发现test3已经授权成功,只有select权限,如下图:

image

4.4、为新建用户授权

遵循权限最小化原则。

4.4.1、查看用户权限

方法一:

像上面一样,用select查询

01
mysql>select *from mysql.user where User='test3'\G;

方法二:

01
mysql> show grantsfor test3;