当前位置:嗨网首页>书籍在线阅读

08-数据库相关的安全问题

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

本节介绍一些常见的数据库安全问题,这些问题大多数是由于账号的管理不当造成的。希望读者读完本节后能够认识到账号管理的重要性,同时加强对账号管理的安全意识。

1.删除匿名账号

在某些版本中,安装完毕MySQL后,会自动安装一个空账号,此账号具有对test数据库的全部权限,如下所示:

[zzx@bj34 zzx]$ mysql -uroot -p

Enter password:

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 56064 to server version: 4.1.13-standard-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use mysql

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> select * from user \G;

……

2. row

Host: localhost

User:

Password:

Select_priv: N

Insert_priv: N

Update_priv: N

Delete_priv: N

Create_priv: N

Drop_priv: N

Reload_priv: N

Shutdown_priv: N

Process_priv: N

File_priv: N

Grant_priv: N

References_priv: N

Index_priv: N

Alter_priv: N

Show_db_priv: N

Super_priv: N

Create_tmp_table_priv: N

Lock_tables_priv: N

Execute_priv: N

Repl_slave_priv: N

Repl_client_priv: N

ssl_type:

ssl_cipher:

x509_issuer:

x509_subject:

max_questions: 0

max_updates: 0

max_connections: 0

mysql> select * from db \G;

1. row

Host: %

Db: test

User:

Select_priv: Y

Insert_priv: Y

Update_priv: Y

Delete_priv: Y

Create_priv: Y

Drop_priv: Y

Grant_priv: N

References_priv: Y

Index_priv: Y

Alter_priv: Y

Create_tmp_table_priv: Y

Lock_tables_priv: Y

普通用户只需要执行mysql命令即可登录MySQL数据库,这个时候默认使用了空用户,可以在test数据库里面做各种操作,比如可以创建一个大表,占用大量磁盘空间,这样将给系统造成安全隐患,如下所示:

[zzx@bj34 zzx]$ mysql

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 56073 to server version: 4.1.13-standard-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use test

Database changed

mysql> show tables;

Empty set (0.00 sec)

mysql> create table t1(id int);

Query OK, 0 rows affected (0.00 sec)

mysql> insert into t1 values(1);

Query OK, 1 row affected (0.00 sec)

建议删除此空账号,或者对此账号加密码:

[zzx@bj34 zzx]$ mysql -uroot -p

Enter password:

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 56074 to server version: 4.1.13-standard-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> drop user ''@'localhost';

Query OK, 0 rows affected (0.00 sec)

[zzx@bj34 zzx]$ mysql

'ERROR 1045 (28000): Access denied for user 'zzx'@'localhost' (using password: NO)

2.给root账号设置口令

MySQL安装完毕后,root的默认口令为空,需要马上修改root口令:

[root@localhost zzx]# mysql -uroot

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 15

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> set password=password('newpassword');

Query OK, 0 rows affected (0.00 sec)

不写密码登录将被拒绝:

[root@localhost zzx]# mysql -uroot

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

3.设置安全密码

密码的安全体现在以下两个方面:

设置安全的密码,建议使用6位以上字母、数字、下划线和一些特殊字符组合而成的字符串;

使用上的安全,使用密码期间尽量保证使用过程安全,不会被别人窃取。

第一点就不说了,越长、越复杂、越没有规律的密码越安全。对于第二点,可以总结一下,在日常工作中,使用密码一般是采用以下几种方式。

(1)直接将密码写在命令行中:

[root@localhost zzx]# mysql -uroot -p123

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 2

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

(2)交互式方式输入密码:

[root@localhost zzx]# mysql -uroot -p

Enter password:

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 3

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>

(3)将用户名和密码写在配置文件里面,连接的时候自动读取。比如应用连接数据库或者执行一些批处理脚本。对于这种方式,MySQL供了一种方法,在my.cnf里面写入连接信息:

[client]

user=username

password=password

然后对配置文件进行严格的权限限制,例如:

chmod +600 my.cnf

以上是3种常见的密码使用方式。很显然,第1种最不安全,因为它将密码写成为明文;第2种比较安全,但是只能使用在交互式的界面下;第3种使用比较方便,但是需要将配置文件设置严格的存取权限,而且任何只要可以登录操作系统的用户都可以自动登录,存在一定的安全隐患。

第3种方法通常使用不多,下面举一个例子。

输入mysql无法登录。

[root@localhost zzx]# mysql

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

修改配置文件,加入连接信息。

[root@localhost zzx]# vi /etc/my.cnf

[client]

user=root

password=123

重启数据库后,输入mysql。

[root@localhost zzx]# service mysql restart

Shutting down MySQL.[ OK ]

Starting MySQL[ OK ]

[root@localhost zzx]# mysql

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 1

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> select current_user();

+----------------+

| current_user() |

+----------------+

| root@localhost |

+----------------+

1 row in set (0.00 sec)

4.只授予账号必需的权限

只需要赋予普通用户必需的权限,比如:

Grant select,insert,update,delete on tablename to 'username'@'hostname';

在很多情况下,DBA由于图方便,而经常赋予用户 all privileges权限,这个 all privileges到底具体包含哪些权限呢?来看下面的例子:

mysql> grant all privileges on test1.* to 'z1'@'localhost';

Query OK, 0 rows affected (0.00 sec)

mysql> select * from db where user='z1' \G;

1. row

Host: localhost

Db: test1

User: z1

Select_priv: Y

Insert_priv: Y

Update_priv: Y

Delete_priv: Y

Create_priv: Y

Drop_priv: Y

Grant_priv: N

References_priv: Y

Index_priv: Y

Alter_priv: Y

Create_tmp_table_priv: Y

Lock_tables_priv: Y

Create_view_priv: Y

Show_view_priv: Y

Create_routine_priv: Y

Alter_routine_priv: Y

Execute_priv: Y

1 row in set (0.00 sec)

all privileges里面的权限远远超过了我们一般应用所需要的权限。而且,有些权限如果误操作,将会产生非常严重的后果,比如 drop_priv 等。因此,赋予用户权限的时候越具体,则对数据库越安全。

5.除root外,任何用户不应有mysql库user表的存取权限

由于MySQL中可以通过更改mysql数据库的user表进行权限的增加、删除、变更等操作,因此,除了root以外,任何用户都不应该拥有对user表的存取权限(SELECT、UPDATE、INSERT、DELETE等),否则容易造成系统的安全隐患。下例中对普通用户z3授予了user表的存取权限,看看会对系统产生了怎样的安全隐患。

(1)创建普通用户z3,拥有对mysql数据库中user表的各种权限。

[root@localhost zzx]# mysql -uroot -pabc

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 36

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> grant select,update,insert,delete on mysql.user to z3@localhost;

Query OK, 0 rows affected (0.00 sec)

mysql> exit

Bye

(2)用z3来更新root权限。

[root@localhost zzx]# mysql -uz3

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 37

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use mysql

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> update user set password=password('abcd') where user='root' and host='localhost';

Query OK, 1 row affected (0.00 sec)

Rows matched: 1 Changed: 1 Warnings: 0

(3)当数据库重启或者root刷新权限表后,root登录时密码已经被更改。

[root@localhost zzx]# mysql -uroot –pabc

Enter password:

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

[root@localhost zzx]# mysql -uroot –pabcd

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 40

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> exit

6.不要把FILE、PROCESS或SUPER权限授予管理员以外的账号

FILE权限主要有以下两种作用。

将数据库的信息通过SELECT…INTO OUTFILE…写到服务器上有写权限的目录下,作为文本格式存放。具有权限的目录也就是启动MySQL时的用户权限目录。

可以将有读权限的文本文件通过LOAD DATA INFILE…命令写入数据库表,如果这些表中存放了很重要的信息,将对系统造成很大的安全隐患。

在下例中详细描述了FILE权限可能造成的隐患。

(1)连接数据库并创建测试表t。

[root@localhost zzx]# mysql -uroot -p

Enter password:

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 43

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use mysql

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> create table t1 (name varchar(500));

Query OK, 0 rows affected (0.04 sec)

(2)将/etc/passwd文件加载到表t1中。

mysql> load data infile '/etc/passwd' into table t1;

Query OK, 35 rows affected (0.00 sec)

Records: 35 Deleted: 0 Skipped: 0 Warnings: 0

(3)查看表t1的内容。

mysql> select * from t1;

+-----------------------------------------------------------------------+

| name |

+-----------------------------------------------------------------------+

| root:x:0:0:root:/root:/bin/bash |

| bin:x:1:1:bin:/bin:/sbin/nologin |

| daemon:x:2:2:daemon:/sbin:/sbin/nologin|

| adm:x:3:4:adm:/var/adm:/sbin/nologin |

| lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin |

| sync:x:5:0:sync:/sbin:/bin/sync |

| shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown |

| … |

||

| oracle:x:501:502::/home/oracle:/bin/bash |

| zzx:x:502:503::/home/zzx:/bin/bash |

| mysql:x:102:102:MySQL server:/var/lib/mysql:/bin/bash |

+------------------------------------------------------------------------+

35 rows in set (0.00 sec)

这样,重要的用户信息/etc/passwd内容将被写入表t1,造成系统安全隐患。

PROCESS权限能被用来执行“show processlist”命令,查看当前所有用户执行的查询的明文文本,包括设定或改变密码的查询。在默认情况下,每个用户都可以执行“show processlist”命令,但是只能查询本用户的进程。因此,对PROCESS权限管理不当,有可能会使得普通用户能够看到管理员执行的命令。

下例中对普通用户赋予了PROCESS权限,来看看会造成什么安全隐患。

(1)将PROCESS权限授予普通用户:

[zzx@localhost~]$ mysql -uroot -p

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 51

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show processlist;

mysql> grant process on . to 'z1'@'localhost';

Query OK, 0 rows affected (0.00 sec)

(2)锁定表user,可以让进程阻塞,以方便用户看到进程内容:

mysql> lock table user read;

Query OK, 0 rows affected (0.00 sec)

(3)打开另外一个session,用root执行修改密码操作,此时因为user表被锁定,此进程被阻塞挂起:

[zzx@localhost~]$ mysql -uroot -p

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 51

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> set password=password('123');

(4)打开第 3个 session,用 z1登录,执行 show processlist语句:

[zzx@localhost~]$ mysql -uz1

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 59

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show processlist;

+----+------+----------+------+--------+-----+-------+------------------------------+

| Id | User | Host | db | Command| Time| State | Info |

+----+------+----------+------+--------+-----+-------+------------------------------+

| 51 | root | localhost | mysql| Query | 157 | Locked | set password= password('123') |

| 58 | root | localhost| mysql| Sleep | 341|| NULL|

| 59 | z1 | localhost | NULL | Query | 0 | NULL | show processlist |

+----+------+----------+------+--------+-----+--------+-----------------------------+

3 rows in set (0.00 sec)

可以发现,z1显示的进程中清楚地看到了root的修改密码操作,并看到了明文的密码,这将对系统造成严重的安全隐患。

SUPER权限能执行kill命令,终止其他用户进程。在下面的例子中,普通用户拥有了SUPER权限后,便可以任意kill任何用户的进程。

(1)z1登录后想kill掉root修改密码进程(进程号51):

[zzx@localhost~]$ mysql -uz1

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 59

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show processlist;

+----+------+----------+------+---------+------+--------+---------------------------+

| Id | User | Host | db | Command | Time | State | Info |

+----+------+----------+------+---------+------+--------+---------------------------+

| 51 | root | localhost| mysql| Query | 157 | Locked | set password=password('123')|

| 58 | root | localhost | mysql| Sleep | 341 | | NULL |

| 59 | z1 | localhost | NULL | Query | 0 | NULL | show processlist |

+----+------+----------+------+---------+------+--------+---------------------------+

3 rows in set (0.00 sec)

mysql> kill 51;

ERROR 1095 (HY000): You are not owner of thread 51

mysql>

(2)kill失败后,root将super权限赋予z1:

mysql> grant super on . to z1@localhost;

Query OK, 0 rows affected (0.00 sec)

mysql> show grants for z1@localhost;

+-------------------------------------------------+

| Grants for z1@localhost |

+-------------------------------------------------+

| GRANT PROCESS, SUPER ON . TO 'z1'@'localhost' |

+-------------------------------------------------+

1 row in set (0.00 sec)

(3)重新 kill root的进程成功:

[zzx@localhost~]$ mysql -uz1

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 60

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show processlist;

+----+------+-----------+-------+--------+------+-------+---------------------------+

| Id | User | Host | db |Command| Time | State | Info |

+----+------+-----------+-------+--------+------+-------+---------------------------+

| 51 | root | localhost | mysql | Query | 23 |Locked |set password= password('123')|

| 58 | root | localhost | mysql | Sleep | 26 | | NULL |

| 60 | z1 | localhost | NULL | Query | 0 | NULL | show processlist |

+----+------+-----------+-------+---------+------+-------+--------------------------+

3 rows in set (0.00 sec)

mysql> kill 51;

Query OK, 0 rows affected (0.00 sec)

从上面的例子中,可以看到了FILE、PROCESS、SUPER三个管理权限可能带来的安全隐患,因此,除了管理员外,不要把这些权限赋予普通用户。

7.LOAD DATA LOCAL带来的安全问题

LOAD DATA默认读的是服务器上的文件,但是加上LOCAL参数后,就可以将本地具有访问权限的文件加载到数据库中。这在带来方便的同时,也带来了以下安全问题。

可以任意加载本地文件到数据库。

在Web环境中,客户从Web服务器连接,用户可以使用LOAD DATA LOCAL语句来读取Web服务器进程有读访问权限的任何文件(假定用户可以运行SQL服务器的任何命令)。在这种环境中,MySQL服务器的客户实际上是Web服务器,而不是连接Web服务器的用户运行程序。

解决方法是,可以用--local-infile=0选项启动 mysqld从服务器端禁用所有 LOAD DATA LOCAL命令。

对于mysql命令行客户端,可以通过指定--local-infile[=1]选项启用LOAD DATA LOCAL,或通过--local-infile=0选项禁用。类似地,对于mysqlimport,--local或 -L选项启用本地数据文件装载。在任何情况下,成功进行本地装载需要服务器启用相关选项。

8.使用MERGE存储引擎潜藏的安全漏洞

MERGE存储引擎的表在某些版本中可能存在以下安全漏洞:

用户A赋予表T的权限给用户B;

用户B创建一个包含T的MERGE表,做各种操作;

用户A收回对T的权限。

存在的安全隐患是用户B通过MERGE表仍然可以访问表A中的数据。下面的例子描述了这个过程。

(1)用root创建用户z1,拥有数据库test1的所有权限:

mysql> grant all privileges on test1.* to z1@localhost;

Query OK, 0 rows affected (0.00 sec)

(2)z1登录后创建表t2并插入测试数据:

mysql> create table t2 (id int);

Query OK, 0 rows affected (0.01 sec)

mysql> insert into t2 values(2);

Query OK, 1 row affected (0.00 sec)

(3)z1在t1和t2上创建MERGE表:

mysql> create table t12 (id int) engine=merge union=(t1,t2);

Query OK, 0 rows affected (0.01 sec)

mysql> select * from t12;

+------+

| id |

+------+

| 1 |

| 1 |

| 2 |

+------+

3 rows in set (0.00 sec)

(4)root收回z1在表t1上的所有权限:

mysql> revoke all privileges on test1.t1 from z1@localhost;

Query OK, 0 rows affected (0.00 sec)

mysql> show grants for z1@localhost;

+----------------------------------------+

| Grants for z1@localhost|

+----------------------------------------+

| GRANT USAGE ON . TO 'z1'@'localhost' |

+----------------------------------------+

1 row in set (0.00 sec)

(5)z1通过t12依然能够访问t1的数据:

[root@localhost test1]# mysql -uz1

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 21

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use test1

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> show tables;

+-----------------+

| Tables_in_test1 |

+-----------------+

| t12 |

| t2 |

+-----------------+

2 rows in set (0.00 sec)

mysql> select * from t2;

+------+

| id |

+------+

| 2 |

+------+

1 row in set (0.00 sec)

mysql> select * from t12;

+------+

| id |

+------+

| 1 |

| 1 |

| 2 |

+------+

3 rows in set (0.00 sec)

9.DROP TABLE命令并不收回以前的相关访问授权

DROP表的时候,其他用户对此表的权限并没有被收回,这样导致重新创建同名的表时,以前其他用户对此表的权限会自动赋予,进而产生权限外流。因此,在删除表时,要同时取消其他用户在此表上的相应权限。

下面的例子说明了不收回相关访问授权的隐患。

(1)用root创建用户z1,授予对test1下所有表的select权限:

mysql> grant select on test1.* to z1@localhost;

Query OK, 0 rows affected (0.00 sec)

mysql> show grants for z1@localhost;

+-----------------------------------------------+

| Grants for z1@localhost |

+-----------------------------------------------+

| GRANT USAGE ON . TO 'z1'@'localhost' |

| GRANT SELECT ON 'test1'.* TO 'z1'@'localhost' |

+-----------------------------------------------+

2 rows in set (0.00 sec)

(2)z1登录,测试权限:

[root@localhost test1]# mysql -uz1

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 43

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use test1

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> show tables;

+-----------------+

| Tables_in_test1 |

+-----------------+

| t1|

| t12|

| t2|

+-----------------+

3 rows in set (0.00 sec)

(3)root登录,删除表t1:

[root@localhost test1]# mysql -uroot

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

[root@localhost test1]# mysql -uroot -p123

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 45

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use test1

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> drop table t1;

Query OK, 0 rows affected (0.00 sec)

mysql> exit

Bye

(4)z1登录,再次测试权限:

[root@localhost test1]# mysql -uz1

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 46

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use test1

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> show tables;

+-----------------+

| Tables_in_test1 |

+-----------------+

| t12 |

| t2 |

+-----------------+

2 rows in set (0.00 sec)

(5)此时t1表已经看不到了:

mysql> show grants for z1@localhost;

+-----------------------------------------------+

| Grants for z1@localhost |

+-----------------------------------------------+

| GRANT USAGE ON . TO 'z1'@'localhost' |

| GRANT SELECT ON test1.* TO 'z1'@'localhost' |

+-----------------------------------------------+

2 rows in set (0.00 sec)

权限仍然显示对test1下所有表的SELECT(安全漏洞)。

(6)root再次登录,创建t1表:

[root@localhost test1]# mysql -uroot -p123

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 48

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> create table t1(id int);

Query OK, 0 rows affected (0.03 sec)

mysql> exit

(7)z1登录,对t1权限依旧存在:

[root@localhost test1]# mysql -uz1 test1

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 49

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show tables;

+-----------------+

| Tables_in_test1 |

+-----------------+

| t1 |

| t12|

| t2|

+-----------------+

3 rows in set (0.00 sec)

mysql> select * from t1;

Empty set (0.00 sec)

注意:对表做删除后,其他用户对此表的权限不会自动收回,一定记住要手工收回。

10.使用SSL

SSL(Secure Socket Layer,安全套接字层)是一种安全传输协议,最初由Netscape公司所开发,用以保障在Internet上数据传输的安全,利用数据加密(Encryption)技术,可确保数据在网络上的传输过程中不会被截取及窃听。

SSL协议提供的服务主要有:

(1)认证用户和服务器,确保数据发送到正确的客户机和服务器;

(2)加密数据以防止数据中途被窃取;

(3)维护数据的完整性,确保数据在传输过程中不被改变。

在MySQL中,要想使用SSL进行安全传输,需要在命令行中或选项文件中设置“--ssl”选项。

对于服务器,“--ssl”选项规定该服务器允许 SSL 连接。对于客户端程序,它允许客户使用SSL连接服务器。单单该选项不足以使用SSL连接,还必须指定--ssl-ca、--ssl-cert和--ssl-key选项。如果不想启用SSL,则可以将选项指定为--skip-ssl或--ssl=0。

注意:如果编译的服务器或客户端不支持SSL,则使用普通的未加密的连接。

确保使用SSL连接的安全方式是,使用含REQUIRE SSL子句的GRANT语句在服务器上创建一个账户,然后使用该账户来连接服务器,服务器和客户端均应启用SSL支持。下面的例子创建了一个含REQUIRE SSL子句的账号:

mysql> grant select on . to z4 identified by '123' REQUIRE ssl;

Query OK, 0 rows affected (0.03 sec)

--ssl-ca=file_name 含可信SSL CA的清单的文件的路径。

--ssl-cert=file_name SSL证书文件名,用于建立安全连接。

--ssl-key=file_name SSL密钥文件名,用于建立安全连接。

11.如果可能,给所有用户加上访问IP限制

对数据库来说,我们希望从客户端过来的连接都是安全的,因此,就很有必要在创建用户时指定可以进行连接的服务器IP或者HOSTNAME,只有符合授权的IP或者HOSTNAME才可以进行数据库访问。

12.REVOKE命令的漏洞

当用户被多次赋予权限后,由于各种原因,需要将此用户的权限全部取消,此时,REVOKE命令可能并不会按照我们的意愿执行,来看下面的例子。

(1)连续赋予用户两次权限,其中,第2次是对所有数据库的所有权限。

mysql> grant select,insert on test1.* to z1@localhost;

Query OK, 0 rows affected (0.00 sec)

mysql> grant all privileges on . to z1@localhost;

Query OK, 0 rows affected (0.00 sec)

mysql> show grants for z1@localhost;

+-------------------------------------------------------+

| Grants for z1@localhost |

+-------------------------------------------------------+

| GRANT ALL PRIVILEGES ON . TO 'z1'@'localhost' |

| GRANT SELECT, INSERT ON test1.* TO 'z1'@'localhost' |

+-------------------------------------------------------+

2 rows in set (0.00 sec)

(2)此时,需要取消此用户的所有权限。

mysql> revoke all privileges on . from z1@localhost;

Query OK, 0 rows affected (0.00 sec)

(3)我们很可能以为,此时用户已经没有任何权限了,而不会再去查看他的权限表。而实际上,此时的用户依然拥有test1上的SELECT和INSERT权限。

mysql> show grants for z1@localhost;

+-------------------------------------------------------+

| Grants for z1@localhost |

+-------------------------------------------------------+

| GRANT USAGE ON . TO 'z1'@'localhost' |

| GRANT SELECT, INSERT ON test1.* TO 'z1'@'localhost' |

+-------------------------------------------------------+

2 rows in set (0.00 sec)

(4)此时,再次用z1登录,测试一下是否能对test1数据库做操作。

[zzx@localhost~]$ mysql -uz1

Welcome to the MySQL monitor. Commands end with ; or \g.

Your MySQL connection id is 26

Server version: 5.0.41-community-log MySQL Community Edition (GPL)

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> use test1

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A

Database changed

mysql> show tables;

+-----------------+

| Tables_in_test1 |

+-----------------+

| t1|

| t12|

| t2|

+-----------------+

3 rows in set (0.00 sec)

mysql> insert into t1 values(1);

Query OK, 1 row affected (0.00 sec)

这个是MySQL权限机制造成的隐患,在一个数据库上多次赋予权限,权限会自动合并;但是在多个数据库上多次赋予权限,每个数据库上都会认为是单独的一组权限,必须在此数据库上用REVOKE命令来单独进行权限收回,而REVOKE ALL PRIVILEGES ON .并不会替用户自动完成这个过程。