博客是我工作的好帮手,遇到困难就来博客找资料
分类: 系统运维
2017-02-20 21:31:06
root权限一定要只允许本机登陆,并且MySQL安全目录权限一定要只允许本地,root用户一定要密钥认证登陆系统(这涉及到系统安全的优化)而且MySQL的安装目录权限一定要合理设置,并且mysql用户不可登陆,只作为启动用。MySQL的binlog要合理管理,配置好权限。
1、mysqladmin -u root password "newpass"
如果已经配置了密码:
mysqladmin -uroot -prenzhiyuan password '123456'
2、用SET PASSWORD命令
mysql> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('renzhiyuan');
Query OK, 0 rows affected (0.00 sec)
mysql>
3、UPDATE
mysql> UPDATE user SET Password = PASSWORD('123456') WHERE user = 'root';
Query OK, 4 rows affected (0.00 sec)
Rows matched: 4 Changed: 4 Warnings: 0
2.1.1)MySQL的历史命令记录:
[root@mysql ~]# cat .mysql_history
SET PASSWORD FOR 'root'@'localhost' = PASSWORD('renzhiyuan');
show databases;
use mysql;
select host,password,user from user;
grant all on *.* to root@'192.168.1.243' identified by 'renzhiyuan';
flush privileges;
show databases;
flush privileges;
[root@mysql ~]#
2.2.2)查看binlog可以查到明文密码(5.6后版本进行了修复)
2.3.3)以通过授权表直接越过密码。
2.4.4)明文登陆MySQL带来的安全问题
[root@MySQL ~]# ll
总用量 66352
-rw-r--r-- 1 root root 67940718 12月 21 2016 2016-12-21-07-00-01.sql
[root@MySQL ~]# du -sh 2016-12-21-07-00-01.sql
65M 2016-12-21-07-00-01.sql
[root@MySQL ~]# tar -czf - 2016-12-21-07-00-01.sql |openssl enc -e -aes256 -out MySQLbak_$(date +%F-%H-%M-%S).tar.gz
enter aes-256-cbc encryption password:
Verifying - enter aes-256-cbc encryption password: #加密密码
[root@MySQL ~]# ll
总用量 76536
-rw-r--r-- 1 root root 67940718 12月 21 2016 2016-12-21-07-00-01.sql
-rw-r--r-- 1 root root 10426544 1月 28 13:23 MySQLbak_2016-01-28-13-23-10.tar.gz
[root@MySQL ~]# du -sh *
65M 2016-12-21-07-00-01.sql
10M MySQLbak_2016-01-28-13-23-10.tar.gz
[root@MySQL ~]# mv 2016-12-21-07-00-01.sql /opt/
[root@MySQL ~]# ll
总用量 10184
-rw-r--r-- 1 root root 10426544 1月 28 13:23 MySQLbak_2016-01-28-13-23-10.tar.gz
[root@MySQL ~]# ll
总用量 10184
-rw-r--r-- 1 root root 10426544 1月 28 13:23 MySQLbak_2016-01-28-13-23-10.tar.gz
[root@MySQL ~]# openssl enc -d -aes256 -in MySQLbak_2016-01-28-13-23-10.tar.gz |tar xz -C /root/
enter aes-256-cbc decryption password: #错误密码
gzip: stdin: not in gzip format
tar: Child died with signal 13
tar: Error is not recoverable: exiting now
error writing output file
[root@MySQL ~]# openssl enc -d -aes256 -in MySQLbak_2016-01-28-13-23-10.tar.gz |tar xz -C /root/
enter aes-256-cbc decryption password: #正确密码
[root@MySQL ~]# ll
总用量 76536
-rw-r--r-- 1 root root 67940718 12月 21 2016 2016-12-21-07-00-01.sql
-rw-r--r-- 1 root root 10426544 1月 28 13:23 MySQLbak_2016-01-28-13-23-10.tar.gz
[root@MySQL ~]#
enc - openssl 命令使用加密进行编码
-e – 用来加密输入文件的 enc 命令选项,这里是指前一个 tar 命令的输出
-aes256 – 加密用的算法
-out – 用于指定输出文件名的 enc 命令选项,这里文件名是 secured.tar.gz
-d – 用于解密文件
-C – 提取内容到指定目录
一.权限表
mysql数据库中的3个权限表:user 、db、 host
权限表的存取过程是:
1)先从user表中的host、 user、 password这3个字段中判断连接的IP、用户名、密码是否存在表中,存在则通过身份验证;
2) 通过权限验证,进行权限分配时,按照user表db表中的tables_priv 和columns_priv的顺序进行分配。即先检查全局权限表 user,
如果user中对应的权限为Y,则此用户对所有数据库的权限都为Y,将不再检查db, tables_priv,columns_priv;
如果为N,则到db表中检查此用户对应的具体数据库,并得到db中为Y的权限;如果db中为N,则检 查tables_priv中此数据库对应的具体表,取得表中的权限Y,以此类推。
二.MySQL各种权限(共27个)
(以下操作都是以root身份登陆进行grant授权,以p1@localhost身份登陆执行各种命令。)
1. usage
连接(登陆)权限,建立一个用户,就会自动授予其usage权限(默认授予)。
mysql> grant usage on *.* to ‘p1′@’localhost’ identified by ‘123′;
该权限只能用于数据库登陆,不能执行任何操作;且usage权限不能被回收,也即REVOKE用户并不能删除用户。
2. select
必须有select的权限,才可以使用select table
mysql> grant select on pyt.* to ‘p1′@’localhost’;
mysql> select * from shop;
3. create
必须有create的权限,才可以使用create table
mysql> grant create on pyt.* to ‘p1′@’localhost’;
4. create routine
必须具有create routine的权限,才可以使用{create |alter|drop} {procedure|function}
mysql> grant create routine on pyt.* to ‘p1′@’localhost’;
当授予create routine时,自动授予EXECUTE, ALTER ROUTINE权限给它的创建者:
mysql> show grants for ‘p1′@’localhost’;
+—————————————————————————+
Grants for p1@localhost
+————————————————————————–+
| GRANT USAGE ON *.* TO ‘p1′@’localhost’ IDENTIFIED BY PASSWORD ‘*23AE809DDACAF96AF0FD78ED04B6A265E05AA257′ |
| GRANT SELECT, CREATE, CREATE ROUTINE ON `pyt`.* TO ‘p1′@’localhost’|
| GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE `pyt`.`pro_shop1` TO ‘p1′@’localhost’ |
+————————————————————————————-+
5. create temporary tables(注意这里是tables,不是table)
必须有create temporary tables的权限,才可以使用create temporary tables.
mysql> grant create temporary tables on pyt.* to ‘p1′@’localhost’;
[mysql@mydev ~]$ mysql -h localhost -u p1 -p pyt
mysql> create temporary table tt1(id int);
6. create view
必须有create view的权限,才可以使用create view
mysql> grant create view on pyt.* to ‘p1′@’localhost’;
mysql> create view v_shop as select price from shop;
7. create user
要使用CREATE USER,必须拥有mysql数据库的全局CREATE USER权限,或拥有INSERT权限。
mysql> grant create user on *.* to ‘p1′@’localhost’;
或:mysql> grant insert on *.* to p1@localhost;
8. insert
必须有insert的权限,才可以使用insert into ….. values….
9. alter
必须有alter的权限,才可以使用alter table
alter table shop modify dealer char(15);
10. alter routine
必须具有alter routine的权限,才可以使用{alter |drop} {procedure|function}
mysql>grant alter routine on pyt.* to ‘p1′@’ localhost ‘;
mysql> drop procedure pro_shop;
Query OK, 0 rows affected (0.00 sec)
mysql> revoke alter routine on pyt.* from ‘p1′@’localhost’;
[mysql@mydev ~]$ mysql -h localhost -u p1 -p pyt
mysql> drop procedure pro_shop;
ERROR 1370 (42000): alter routine command denied to user ‘p1′@’localhost’ for routine ‘pyt.pro_shop’
11. update
必须有update的权限,才可以使用update table
mysql> update shop set price=3.5 where article=0001 and dealer=’A’;
12. delete
必须有delete的权限,才可以使用delete from ….where….(删除表中的记录)
13. drop
必须有drop的权限,才可以使用drop database db_name; drop table tab_name;
drop view vi_name; drop index in_name;
14. show database
通过show database只能看到你拥有的某些权限的数据库,除非你拥有全局SHOW DATABASES权限。
对于p1@localhost用户来说,没有对mysql数据库的权限,所以以此身份登陆查询时,无法看到mysql数据库:
mysql> show databases;
+——————–+
| Database |
+——————–+
| information_schema|
| pyt |
| test |
+——————–+
15. show view
必须拥有show view权限,才能执行show create view。
mysql> grant show view on pyt.* to p1@localhost;
mysql> show create view v_shop;
16. index
必须拥有index权限,才能执行[create |drop] index
mysql> grant index on pyt.* to p1@localhost;
mysql> create index ix_shop on shop(article);
mysql> drop index ix_shop on shop;
17. excute
执行存在的Functions,Procedures
mysql> call pro_shop1(0001,@a);
+———+
| article |
+———+
| 0001 |
| 0001 |
+———+
mysql> select @a;
+——+
| @a |
+——+
| 2 |
+——+
18. lock tables
必须拥有lock tables权限,才可以使用lock tables
mysql> grant lock tables on pyt.* to p1@localhost;
mysql> lock tables a1 read;
mysql> unlock tables;
19. references
有了REFERENCES权限,用户就可以将其它表的一个字段作为某一个表的外键约束。
20. reload
必须拥有reload权限,才可以执行flush [tables | logs | privileges]
mysql> grant reload on pyt.* to p1@localhost;
ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES
mysql> grant reload on *.* to ‘p1′@’localhost’;
Query OK, 0 rows affected (0.00 sec)
mysql> flush tables;
21. replication client
拥有此权限可以查询master server、slave server状态。
mysql> show master status;
ERROR 1227 (42000): Access denied; you need the SUPER,REPLICATION CLIENT privilege for this operation
mysql> grant Replication client on *.* to p1@localhost;
或:mysql> grant super on *.* to p1@localhost;
mysql> show master status;
+——————+———-+————–+——————+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+——————+———-+————–+——————+
| mysql-bin.000006 | 2111 | | |
+——————+———-+————–+——————+
mysql> show slave status;
22. replication slave
拥有此权限可以查看从服务器,从主服务器读取二进制日志。
mysql> show slave hosts;
ERROR 1227 (42000): Access denied; you need the REPLICATION SLAVE privilege for this operation
mysql> show binlog events;
ERROR 1227 (42000): Access denied; you need the REPLICATION SLAVE privilege for this operation
mysql> grant replication slave on *.* to p1@localhost;
mysql> show slave hosts;
Empty set (0.00 sec)
mysql>show binlog events;
+—————+——-+—————-+———–+————-+————–+
| Log_name | Pos | Event_type | Server_id| End_log_pos|Info | +—————+——-+————–+———–+————-+—————+
| mysql-bin.000005 | 4 | Format_desc | 1 | 98 | Server ver: 5.0.77-log, Binlog ver: 4 | |mysql-bin.000005|98|Query|1|197|use `mysql`; create table a1(i int)engine=myisam|
……………………………………
23. Shutdown
关闭MySQL:
[mysql@mydev ~]$ mysqladmin shutdown
重新连接:
[mysql@mydev ~]$ mysql
ERROR 2002 (HY000): Can’t connect to local MySQL server through socket ‘/tmp/mysql.sock’ (2)
[mysql@mydev ~]$ cd /u01/mysql/bin
[mysql@mydev bin]$ ./mysqld_safe &
[mysql@mydev bin]$ mysql
24. grant option
拥有grant option,就可以将自己拥有的权限授予其他用户(仅限于自己已经拥有的权限)
mysql> grant Grant option on pyt.* to p1@localhost;
mysql> grant select on pyt.* to p2@localhost;
25. file
拥有file权限才可以执行 select ..into outfile和load data infile…操作,但是不要把file, process, super权限授予管理员以外的账号,这样存在严重的安全隐患。
mysql> grant file on *.* to p1@localhost;
mysql> load data infile ‘/home/mysql/pet.txt’ into table pet;
26. super
这个权限允许用户终止任何查询;修改全局变量的SET语句;使用CHANGE MASTER,PURGE MASTER LOGS。
mysql> grant super on *.* to p1@localhost;
mysql> purge master logs before ‘mysql-bin.000006′;
27. process
通过这个权限,用户可以执行SHOW PROCESSLIST和KILL命令。默认情况下,每个用户都可以执行SHOW PROCESSLIST命令,但是只能查询本用户的进程。 mysql> show processlist;
+—-+——+———–+——+———+——+——-+——————+
| Id | User | Host | db | Command | Time | State | Info |
+—-+——+———–+——+———+——+——-+——————+
| 12 | p1 | localhost | pyt | Query | 0 | NULL | show processlist |
+—-+——+———–+——+———+——+——-+——————+
另外,
管理权限(如 super, process, file等)不能够指定某个数据库,on后面必须跟*.*
mysql> grant super on pyt.* to p1@localhost;
ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES
mysql> grant super on *.* to p1@localhost;
Query OK, 0 rows affected (0.01 sec)
数据库安全 5.1. 保护MySQL安装程序文件 5.2. 权限表 5.3. 建立加密连接
5.1. 保护 MySQL安装程序文件
在重设置文件权限时,请先关闭数据库服务器。
用以下命令把MySQL安装程序目录的属主和所属组设置为MySQL管理员帐号的用户名和用户组名。
% chown -R mysql.mysql /usr/local/mysql
另外一种方法是把除数据目录外的所有目录属主设置为root所有,如:
% chown -R root.mysql /usr/local/mysql
% chown -R mysql.mysql /usr/local/mysql/data
设置安装目录及各有关子目录的权限,允许管理员进行所有操作,只允许其他人进行读和执行访问,设置命令如下:
#设置mysql目录
% chmod 755 /usr/local/mysql
or
% chmod u=rwx,go=rx /usr/local/mysql
#设置mysql/bin目录
% chmod 755 /usr/local/mysql/bin
or
% chmod u=rwx,go=rx /usr/local/mysql/bin
#设置mysql/libexec目录
% chmod 700 /usr/local/mysql/libexec
or
% chmod u=rwx,go-rwx /usr/local/mysql/libexec
把数据目录及目录中的所有子目录和文件设置为只允许MySQL管理员访问。
% chmod -R go-rwx /usr/local/mysql/data
如果数据目录下有选项文件或套接字文件,并一些客户需访问这些文件,则可用以下的权限设置,使客户在没有读权限的前提下使用这些文件:
% chmod go+x /usr/local/mysql/data
mysql.sock 套接字文件一般放以/tmp目录下,要确保该目录设置了粘着位,使自户只能删除自已创建的文件,不能删除其他用户创建的文件。
/etc/my.cnf中公共选项文件,是对所有用户可读的,所以不应把一些敏感信息保存在里面。
.my.cnf是用户专用选项文件,要确保只有该用户有权访问 这样设置以后,只有MySQL管理员才能启动服务器。
5.2. 权限表
MySQL服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。下面分别介绍一下这些表的结构和内容:
user权限表:记录允许连接到服务器的用户帐号信息,里面的权限是全局级的。
db权限表:记录各个帐号在各个数据库上的操作权限。
table_priv权限表:记录数据表级的操作权限。
columns_priv权限表:记录数据列级的操作权限。
host权限表:配合db权限表对给定主机上数据库级操作权限作更细致的控制。这个权限表不受GRANT和REVOKE语句的影响。
大家注意到,以上权限没有限制到数据行级的设置。在MySQL只要实现数据行级控制就要通过编写程序(使用GET-LOCK()函数)来实现。
MySQL的版本很多,所以权限表的结构在不同版本间会有不同。如果出现这种情况,可用mysql_fix_privilege_tables脚本来修正。运行方式如下:
% mysql_fix_privilege_tables rootpassword #这里要给出MySQL的root用户密码
最好一下子升级到MySQL 4.0.4版本,因为4.0.2和4.0.3的db表没有Create_tmp_table_priv和Lock_tables_priv权限。
MySQL的权限表定义了两部份内容,一个部份定义权限的范围,即谁(帐户)可以从哪里(客户端主机)访问什么(数据库、数据表、数据列);另一部份定义权限,即控制用户可以进行的操作。下面是一些常用的权限介绍,可直接在GRANT语句中使用。
CREATE TEMPORARY TABLES,允许创建临时表的权限。
EXECUTE,允许执行存储过程的权限,存储过程在MySQL的当前版本中还没实现。
FILE,允许你通过MySQL服务器去读写服务器主机上的文件。但有一定限制,只能访问对任何用户可读的文件,通过服务器写的文件必须是尚未存在的,以防止服务器写的文件覆盖重要的系统文件。尽管有这些限制,但为了安全,尽量不要把该权限授予普通用户。并且不要以root用户来运行MySQL服务器,因为root 用户可在系统任何地方创建文件。
GRANT OPTION,允许把你自已所拥有的权限再转授给其他用户。
LOCK TABLES,可以使用LOCK TABLES语句来锁定数据表
PROCESS,允许你查看和终止任何客户线程。SHOW PROCESSLIST语句或mysqladmin processlist命令可查看线程,KILL语句或mysqladmin kill命令可终止线程。在4.0.2版及以后的版本中,PROCESS权限只剩下查看线程的能力,终止线程的能力由SUPER权限控制。
RELOAD,允许你进行一些数据库管理操作,如FLUSH,RESET等。它还允许你执行mysqladmin命令:reload,refresh,flush- hosts,flush-logs,flush-privileges,flush- status,flush-tables和flush-threads。
REPLICATION CLIENT,允许查询镜像机制中主服务器和从服务器的位置。
REPLICATION SLAVE,允许某个客户连接到镜像机制中的主服务器并请求发送二进制变更日志。该权限应授予从服务器用来连接主服务器的帐号。在4.0.2版这前,从服务器是用FILE权限来连接的。
SHOW DATABASES,控制用户执行SHOW DATABASES语句的权限。
SUPER,允许终止线程,使用mysqladmin debug命令,使用CHANGE MASTER,PURGE MASTER LOGS以及修改全局级变量的SET语句。SUPER还允许你根据存放在DES密钥文件里的密钥进行DES解密的工作。
user权限表中有一个ssl_type数据列,用来说明连接是否使用加密连接以及使用哪种类型的连接,它是一个ENUM类型的数据列,可能的取值有:
NONE,默认值,表示不需加密连接。
ANY,表示需要加密连接,可以是任何一种加密连接。由GRANT的REQUIRE SSL子句设置。
X509,表示需要加密连接,并要求客户提供一份有效的X509证书。由GRANT的REQUIRE X509子句设置。
SPECIFIED,表示加密连接需满足一定要求,由REQUIRE子句的ISSUER,SUBJECT或CIPHER的值进行设置。只要 ssl_type列的值为SPECIFIED,则MySQL会去检查ssl_cipher(加密算法)、x509_issuer(证书签发者)和 x509_subject(证书主题)列的值。这几列的列类型是BLOB类型的。
user权限表里还有几列是设置帐户资源使用情况的,如果以下数据列中的数全为零,则表示没有限制:
max_connections,每小时可连接服务器的次数。
max_questions,每小时可发出查询命令数。
max_updates,每小时可以发出的数据修改类查询命令数。
设置权限表应注意的事项:
删除所有匿名用户。
查出所有没有口令用户,重新设置口令。可用以下命令查询空口令用户:
mysql> SELECT host,user FROM user WHERE password = '';
尽量不要在host中使用通配符。
最好不要用user权限表进行授权,因为该表的权限都是全局级的。
不要把mysql数据库的权限授予他人,因为该数据库包含权限表。
使用GRANT OPTION权限时不要滥用。
FILE权限可访问文件系统中的文件,所以授权时也要注意。
一个具有FILE权限的用户执行以下语句就可查看服务器上全体可读的文件:
mysql> CREATE TABLE etc_passwd(pwd_entry TEXT);
mysql> LOAD DATA INFILE '/etc/passwd' INTO TABLE etc_passwd;
mysql> SELECT * FROM etc_passwd;
如果MySQL服务器数据目录上的访问权限设置得不好,就会留下让具有FILE权限的用户进入别人数据库的安全漏洞。所以建议把数据目录设置成只能由MySQL服务器读取。下面演示一个利用具有FILE权限的用户读取数据目录中文件权限设置不严密的数据库数据的过程:
mysql> use test;
mysql> create table temp(b longblob);
mysql> show databases #显示数据库名清单,--skip-show-database可禁止该功能
mysql> load data infile './db/xxx.frm' into table temp fields escaped by '' lines terminated by '';
mysql> select * from temp into outfile 'xxx.frm' fields escaped by '' lines terminated by '';
mysql> delete from temp;
mysql> load data infile './db/xxx.MYD' into table temp fields escaped by '' lines terminated by '';
mysql> select * from temp into outfile 'xxx.MYD' fields escaped by '' lines terminated by '';
mysql> delete from temp;
mysql> load data infile './db/xxx.MYI' into table temp fields escaped by '' lines terminated by '';
mysql> select * from temp into outfile 'xxx.MYI' fields escaped by '' lines terminated by '';
mysql> delete from temp;
这样,你的数据库就给人拷贝到本地了。如果服务器是运行在root用户下,那危害就更大了,因为root可在服务器上做任何的操作。所以尽量不要用 root用户来运行服务器。
只把PROCESS权限授予可信用户,该用户可查询其他用户的线程信息。
不要把RELOAD权限授予无关用户,因为该权限可发出FLUSH或RESET语句,这些是数据库管理工具,如果用户不当使用会使数据库管理出现问题。
ALTER权限也不要授予一般用户,因为该权限可更改数据表。
GRANT语句对权限表的修改过程:
当你发送一条GRANT语句时,服务器会在user权限表里创建一个记录项并把你用户名、主机名和口令记录在User、Host和Password 列中。如果设置了全局权限,由把该设置记录在相在的权限列中。
如果在GRANT里设置了数据库级权限,你给出的用户名和主机名就会记录到db权限表的User和Host列中,数据库名记录在Db列中,权限记录到相关的权限列中。
接着是到数据表和数据列级的权限设置,设置方法和上面的一样。服务器会把用户名、主机名、数据库名以及相应的数据表名和数据列名记录到数据表中。
删除用户权限其实就是把这些权限表中相应的帐号记录全部删除即可。
5.3. 建立加密连接
加密连接可提高数据的安全性,但会降低性能。要进行加密连接,必须满足以下要求:
user权限表里要有相关的SSL数据列。如果安装的MySQL服务器是4.0.0版的,user权限表已包含相关的SSL数据列,否则,我们也可用mysql_fix_privilege_tables脚本升级权限表。
服务器和客户程序都已经编译有OpenSSL支持。首先要安装openssl,在编译时MySQL服务器时加--with-vio和--with- openssl选项加上openssl支持。可用以下语句查询服务器是否支持SSL:
mysql> show variables like 'have_openssl';
在启动服务器时用有关选项指明证书文件和密钥文件的位置。
在建立加密连接前,要准备三个文件,一个CA证书,是由可信赖第三方出具的证书,用来验证客户端和服务器端提供的证书。
CA证书可向商业机构购买,也可自行生成。
第二个文件是证书文件,用于在连接时向对方证明自已身份的文件。
第三个文件是密钥文件,用来对在加密连接上传输数据的加密和解密。
MySQL服务器端的证书文件和密钥文件必须首先安装,在sampdb发行版本的ssl目录里有几个供参考的样本文件:ca-cert.pem(CA证书),server-cert.pem(服务器证书),server-key.pem(服务器公共密钥)。把这几个文件拷贝到服务器的数据目录中,再在选项文件里加上以下内容:
[mysqld]
ssl-ca=/usr/local/mysql/data/ca-cert.pem
ssl-cert=/usr/local/mysql/data/server-cert.pem
ssl-key=/usr/local/mysql/data/server-key.pem
重启服务器,使配置生效。
要想让某个客户程序建立加密连接,必须在调用这个客户程序时用有关选项告诉它在哪里能找到其证书文件和密钥文件。在sampdb发行版的ssl目录中提供了 client-cert.pem(客户证书文件),client-key.pem(客户密钥文件),CA证书与服务器使用同样的ca- cert.pem。把他们拷贝到个人目录下,并在.my.cnf选项文件中指出文件位置,如:
[mysql]
ssl-ca=/home/mysql/ca-cert.pem
ssl-cert=/home/mysql/client-cert.pem
ssl-key=/home/mysql/client-key.pem
配置完成后,调用mysql程序运行\s或SHOW STATUS LIKE 'SSL%'命令,如果看到SSL:的信息行就说明是加密连接了。如果把SSL相关的配置写进选项文件,则默认是加密连接的。也可用mysql程序的 --skip-ssl选项取消加密连接。如果用命令行方式启用加密连接可以这样写:
% mysql --ssl-ca=ca-cert.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem
可用GRANT语句的REQUIRE SSL选项来强制用户使用加密连接。
使用sampdb发行版的证书可以建立一个加密连接,但由于该文件已公开,所以安全性不好,我们可以在测试成功后自行建立证书或购买商业证书,以提高安全性。如何自行建立SSL证书的文档在sampdb发行版的ssl/README文件里有说明。
1、避免从互联网访问MySQL数据库,确保特定主机才拥有访问特权
直接通过本地网络之外的计算机改变生产环境中的数据库是异常危险的。有时,管理员会打开主机对数据库的访问:
> GRANT ALL ON *.* TO ';root'@'%'
这其实是完全放开了对root的访问。所以,把重要的操作限制给特定主机非常重要:
> GRANT ALL ON *.* TO 'root'@'localhost';
> GRANT ALL ON *.* TO 'root'@'myip.athome'
> FLUSH PRIVILEGES
此时,你仍有完全的访问,但只有指定的IP(不管其是否静态)可以访问。
2、定期备份数据库
任何系统都有可能发生灾难。服务器、MySQL也会崩溃,也有可能遭受入侵,数据有可能被删除。只有为最糟糕的情况做好了充分的准备,才能够在事后快速地从灾难中恢复。企业最好把备份过程作为服务器的一项日常工作。
3、禁用或限制远程访问
前面说过,如果使用了远程访问,要确保只有定义的主机才可以访问服务器。这一般是通过TCP wrappers、iptables或任何其它的防火墙软件或硬件实现的。
为限制打开网络socket,管理员应当在my.cnf或my.ini的[mysqld]部分增加下面的参数:
skip-networking
这些文件位于windows的C:\Program Files\MySQL\MySQL Server 5.1文件夹中,或在Linux中,my.cnf位于/etc/,或位于/etc/mysql/。这行命令在MySQL启动期间,禁用了网络连接的初始化。请注意,在这里仍可以建立与MySQL服务器的本地连接。
另一个可行的方案是,强迫MySQL仅监听本机,方法是在my.cnf的[mysqld]部分增加下面一行:
bind-address=127.0.0.1
如果企业的用户从自己的机器连接到服务器或安装到另一台机器上的web服务器,你可能不太愿意禁用网络访问。此时,不妨考虑下面的有限许可访问:
mysql> GRANT SELECT, INSERT ON mydb.* TO ';someuser'@'somehost'
这里,你要把someuser换成用户名,把somehost换成相应的主机。
4、设置root用户的口令并改变其登录名
在linux中,root用户拥有对所有数据库的完全访问权。因而,在Linux的安装过程中,一定要设置root口令。当然,要改变默认的空口令,其方法如下:
Access MySQL控制台:
$ mysql -u root -p
在MySQL控制台中执行:
> SET PASSWORD FOR 'root'@'localhost' = PASSWORD('new_password');
在实际操作中,只需将上面一行的new_password换成实际的口令即可。
在Linux控制台中更改root口令的另一种方法是使用mysqladmin工具:
$ mysqladmin -u root password new_password
此时,也是将上面一行的new_password换成实际的口令即可。
当然,这是需要使用强口令来避免强力攻击。
为了更有效地改进root用户的安全性,另一种好方法是为其改名。为此,你必须更新表用户中的mySQL数据库。在MySQL控制台中进行操作:
> USE mysql;
> UPDATE user SET user="another_username" WHERE user="root";
> FLUSH PRIVILEGES;
然后,通过Linux访问MySQL控制台就要使用新用户名了:
$ mysql -u another_username -p
5、移除测试(test)数据库
在默认安装的MySQL中,匿名用户可以访问test数据库。我们可以移除任何无用的数据库,以避免在不可预料的情况下访问了数据库。因而,在MySQL控制台中,执行:
> DROP DATABASE test;
6、禁用LOCAL INFILE
另一项改变是禁用”LOAD DATA LOCAL INFILE”命令,这有助于防止非授权用户访问本地文件。在PHP应用程序中发现有新的SQL注入漏洞时,这样做尤其重要。
此外,在某些情况下,LOCAL INFILE命令可被用于访问操作系统上的其它文件(如/etc/passwd),应使用下现的命令:
mysql> LOAD DATA LOCAL INFILE '/etc/passwd' INTO TABLE table1
更简单的方法是:
mysql> SELECT load_file("/etc/passwd")
为禁用LOCAL INFILE命令,应当在MySQL配置文件的[mysqld]部分增加下面的参数:
set-variable=local-infile=0
7、移除匿名账户和废弃的账户
有些MySQL数据库的匿名用户的口令为空。因而,任何人都可以连接到这些数据库。可以用下面的命令进行检查:
mysql> select * from mysql.user where user="";
在安全的系统中,不会返回什么信息。另一种方法是:
mysql> SHOW GRANTS FOR ''@'localhost';
mysql> SHOW GRANTS FOR ';'@'myhost'
如果grants存在,那么任何人都可以访问数据库,至少可以使用默认的数据库“test”。其检查方法如下:
shell> mysql -u blablabla
如果要移除账户,则执行命令:
mysql> DROP USER "";
从MySQL的5.0版开始支持DROP USER命令。如果你使用的老版本的MySQL,你可以像下面这样移除账户:
mysql> use mysql;
mysql> DELETE FROM user WHERE user="";
mysql> flush privileges;
8、降低系统特权
常见的数据库安全建议都有“降低给各方的特权”这一说法。对于MySQL也是如此。一般情况下,开发人员会使用最大的许可,不像安全管理一样考虑许可原则,而这样做会将数据库暴露在巨大的风险中。
为保护数据库,务必保证真正存储MySQL数据库的文件目录是由”mysql” 用户和” mysql”组所拥有的。
shell>ls -l /var/lib/mysql
此外,还要确保仅有用户”mysql”和root用户可以访问/var/lib/mysql目录。
Mysql的二进制文件存在于/usr/bin/目录中,它应当由root用户或特定的”mysql”用户所拥有。对这些文件,其它用户不应当拥有“写”的访问权:
shell>ls -l /usr/bin/my*
9、降低用户的数据库特权
有些应用程序是通过一个特定数据库表的用户名和口令连接到MySQL的,安全人员不应当给予这个用户完全的访问权。
如果攻击者获得了这个拥有完全访问权的用户,他也就拥有了所有的数据库。查看一个用户许可的方法是在MySQL控制台中使用命令SHOW GRANT
>SHOW GRANTS FOR ';user'@'localhost'
为定义用户的访问权,使用GRANT命令。在下面的例子中,user1仅能从dianshang数据库的billing表中选择:
> GRANT SELECT ON billing.dianshang TO 'user1'@'localhost';
> FLUSH PRIVILEGES;
如此一来,user1用户就无法改变数据库中这个表和其它表的任何数据。
另一方面,如果你要从一个用户移除访问权,就应使用一个与GRANT命令类似的REVOKE命令:
> REVOKE SELECT ON billing.ecommerce FROM 'user1'@'localhost';
> FLUSH PRIVILEGES;
10、移除和禁用.mysql_history文件
在用户访问MySQL控制台时,所有的命令历史都被记录在~/.mysql_history中。如果攻击者访问这个文件,他就可以知道数据库的结构。
$ cat ~/.mysql_history
为了移除和禁用这个文件,应将日志发送到/dev/null。
$export MYSQL_HISTFILE=/dev/null
上述命令使所有的日志文件都定向到/dev/null,你应当从home文件夹移除.mysql_history:$ rm ~/.mysql_history,并创建一个到/dev/null的符号链接。
11、安全补丁
务必保持数据库为最新版本。因为攻击者可以利用上一个版本的已知漏洞来访问企业的数据库。
12、启用日志
如果你的数据库服务器并不执行任何查询,建议你启用跟踪记录,你可以通过在/etc/my.cnf文件的[Mysql]部分添加:log =/var/log/mylogfile。
对于生产环境中任务繁重的MySQL数据库,因为这会引起服务器的高昂成本。
此外,还要保证只有root和mysql可以访问这些日志文件。
错误日志
务必确保只有root和mysql可以访问hostname.err日志文件。该文件存放在mysql数据历史中。该文件包含着非常敏感的信息,如口令、地址、表名、存储过程名、代码等,它可被用于信息收集,并且在某些情况下,还可以向攻击者提供利用数据库漏洞的信息。攻击者还可以知道安装数据库的机器或内部的数据。
MySQL日志
确保只有root和mysql可以访问logfileXY日志文件,此文件存放在mysql的历史目录中。
13、改变root目录
Unix操作系统中的chroot可以改变当前正在运行的进程及其子进程的root目录。重新获得另一个目录root权限的程序无法访问或命名此目录之外的文件,此目录被称为“chroot监狱”。
通过利用chroot环境,你可以限制MySQL进程及其子进程的写操作,增加服务器的安全性。
你要保证chroot环境的一个专用目录,如/chroot/mysql。此外,为了方便利用数据库的管理工具,你可以在MySQL配置文件的[client]部分改变下面的参数:
[client]
socket = /chroot/mysql/tmp/mysql.sock
14、禁用LOCAL INFILE命令
LOAD DATA LOCAL INFILE可以从文件系统中读取文件,并显示在屏幕中或保存在数据库中。如果攻击者能够从应用程序找到SQL注入漏洞,这个命令就相当危险了。下面的命令可以从MySQL控制台进行操作:
> SELECT LOAD_FILE("/etc/passwd");
该命令列示了所有的用户。解决此问题的最佳方法是在MySQL配置中禁用它,在CentOS中找到/etc/my.cnf或在Ubuntu中找到/etc/mysql/my.cnf,在[mysqld]部分增加下面一行:set-variable=local-infile=0。搞定。
1、安装完MySQL后
修改root用户密码
5.5以前,rpm包安装完MySQL后,root用户密码为空
5.6中,rpm包安装完MySQL后,会随机生成一个root密码,保存在/root/.mysql_secret
5.7以后,使用mysqld --initialize初始化时,默认会自动生成随机密码,并且不创建除
root@localhost 外的其他账号,也不创建test库;
2、正确授权
mysql库中有4张权限表,user、db、tables_priv、columns_priv,分别对应用户密码、用户对数据库的权限、对表的权限、对列的权限。
当一个用户向MySQL发起请求时,首先会从user表中验证host、user、password,然后再依次验证db、tables_priv、columns_priv,验证过程中,如果db表中对应权限为Y,则此用户对某个库的权限全为Y,将不再验证tables_priv和columns_priv。
对于MySQL中的账户权限相关的安全配置,总结如下:
针对每个网站建立一个单独的账户
为每个网站单独建立一个专属数据库
按照user->db->tables_priv->columns_pri的顺序进行细粒度的权限控制
为每个用户单独配置一个专属数据库,保证当前用户的所有操作只能发生在它自己的数据库中,防止SQL注入发生后,黑客通过注入点访问到系统表
如果有必要,改变MySQL的root用户的用户名(在user表中更改)
3、MySQL网络完全配置
禁止root用户远程登录
防火墙设置
更改默认端口(默认3306),可以从一定程度上防止端口扫描工具的扫描
限制单个用户的连接数量:
[mysqld]
max_user_connections 20
4、文件权限及文件安全
使用非root用户启动MySQL服务
限制启动MySQL的用户的文件权限,同时确保该用户对MySQL的数据文件等有读写权限
可以使用chroot更改根目录,防止非root用户访问到一些敏感文件,比如:/etc/passwd
不要给非root用户授予process和super权限,mysqladmin processlist和show processlist命令会查看到任何用户执行的命令,这可能看到其他用户执行的update user set password=...;命令,super权限可以终止会话、更改系统参数等
不要对表使用软连接(--skip-symbolic-links参数用来禁用这一功能),表的软连接只有MyISAM支持,因为开启表软连接后(尤其是对于使用系统root用户启动MySQL服务的),MySQL用户就可以使用mysqld来删除、重命名数据文件所在位置以外的文件了
如果plugin文件夹可以被MySQL server写,那么用户就可以使用select ... into dumpfile命令把可执行代码写入到里面,可以通过把plugin_dir参数对应的路径设为只读以及调整--secure-file-priv参数来提高安全性
不要给非root用户授予文件读写权限,防止使用load data local infile来提取本地文件(比如提取/etc/passwd里的信息,会对系统安全造成威胁)
[mysqld]
local-infile=0
5、如果有必要,可以删除~/.bash_history文件,防止读取历史命令
# rm .bash_history .mysql_history
# ln -s /dev/null .bash_history
# ln -s /dev/null .mysql_history