Mysql权限组成
Mysql在权限控制这方面,主要有用户模块和权限控制模块组成
用户控制模块主要通过用户名,密码和连接的IP/域名来决定客户端是否可以连进来
权限控制模块由于其容量小且经常使用到,所以在mysql启动的时候就把相应的权限控制表载入到内存中去了。
权限控制的信息存储在mysql的grant table中,有mysql.user,mysql.db, mysql.host,mysql.tables_priv,mysql.columns_priv。
权限控制级别分五个:
全局权限控制global level,权限信息存储在mysql.user表中。对所有的数据库和表都是有效的
grant select,update,delete on *.* to 'wxl'@'localhost';
数据库级别database level,权限信息存储在mysql.db中。
grant alter on test.* to 'wxl'@'localhost';
在选定数据库(use test)的时候,可以使用grant alter on * to 'wxl'@'localhost';
表级别table level, 权限信息存储在mysql.tables_priv,可赋予的权限只有8种,create、delete、drop、index、insert、select,update
grant select on test.t1 to 'wxl'@'localhost';
列级别column level, 仅仅指定某列的访问权限,在权限的的后面加上需控制的列名
grant select(id, name) on test.t1;
routine level,只有execute和alter routine两种,针对procedure和function
grant execute on test.t1 to 'wxl'@'localhost';
权限的控制自顶而下查找符合的权限,即gobal,db,table,column,routine,当查找到符合的权限将不在向下查找。
账号管理
grant priv_type[,priv_type,|ALL ]
on [db,db.table,*.*]
to [user@'%', user@'192.168.88.%', %.xupt.com], ['user'@'localhost']
identified by 'password'
[with grant option]
with grant option一般不给赋值,当一个用户拥有此权限时,他可以授权给别人他所有的一切权限
grant super,process file on *.* to ... 由于这三个权限是管理权限,是全局的。所以不能只授予给特定的库,表,否则将报错。
注意:
-
空的host值等价与'%'
-
在user表的host即使是%或者为空表示所有的IP都可以连接,但是不包括localhost,因此如果要包括本地服务器,必须单独为localhost赋予权限。
-
mysql.user表中的权限是按照一定顺序进行匹配,把具体的放在前面,不确定性大的放在后面,比如192.168.88.121在%的前面。
-
上面的授权操作实际上就是更新相应的权限表,在刷新内存中的权限表(flush privileges)
查看和更改账号的权限
查看: show grants for user@host; ##不写host默认为%
更改:和赋值语句一样,实际上,grant语句在执行的时候,如果权限表中不存在目标账号,则创建,存在的话,则执行权限的新增。
回收:revoke priv_type on 'db.table' from user@host;
如:revoke insert on *.* from w1;
revoke 并不能删除用户,只是回收权限,用户依然可以拥有usage权限,即进入mysql的权限
修改密码
mysqladmin –u username –h host password 'newpasswd'
set password for 'w1'@'localhost' = password('redhat') ##更改自己的密码 set password = password('redhat')
grant usage on *.* to 'root'@'localhost' identified by 'redhat'; ##更改全局的usage
直接修改mysql.user表内容
update mysql.user set password = password('redhat') where user='root' and host='localhost';
flush privileges;
忘记密码
[mysqld]
skip-grant-tables ##跳过权限检测
重启:/etc/init.d/mysqld restart
改密码:mysql> UPDATE user SET Password=password('wang123') WHERE User='root';
或者:killall -TERM mysqld
mysqld_safe --skip-grant-tables &
mysql> UPDATE user SET Password=password('wang123') WHERE User='root';
killall -TERM mysqld
重启:/etc/init.d/mysqld restart
删除用户:
drop user user@host;
注意:grant、revoke、drop在操作时,同时也会刷新内存中的权限表。因此不需要flush privileges;但是当直接修改权限表内容时,应当刷新权限表flush privileges;
Mysql安全
操作系统层面:
严格控制系统的账号和权限:mysql目录属主是root,数据目录属主mysql
避免以root用户运行mysql,因为如果以root运行mysqld进程就会拥有root的权限,并且任何具有拥有FILE权限mysql用户,就可以在系统的任何地方进行写读操作。这样对数据和系统都很不安全
数据库层面的安全问题:
-
删除空账户和test数据库,在MySQL安装完成之后自动会有空账户,他对test可以操作,如果对test进行大量的插入,将浪费掉很多的磁盘空间。
-
给root设定密码,密码长度复杂度要加大。输入密码是不可以明文输入,必须交互输入,也可把用户名和密码写在配置文件my.cnf的client字段中,并给配置文件600权限
-
权限最小化:除了root用户不应有任何人对mysql.user表都更改的权限。
-
不要把FILE,PROCESS(查看所有的show processlist,默认每个用户只能看到自己的), SUPER(终止线程kill)授权给管理员以外的用户
-
load data local 加上local的参数后,就可以读取web服务器有可读的一切文件。可通过在启动时加上 --local-infile=0禁止
-
在删除表的同时,一定检查与此表相关的用户,如果存在相关的用户并具有权限,则应回收其权限,因为如果以后创建和将要删除的表同名的表,那么之前的用户还会有对此表的相关权限的。
-
多次执行grant,造成revoke权限失败:
grant select on testx to w1@localhost
grant all on *.* to w1@localhost
revoke all on *.* from w1@localhost
此时w1的用户依然会拥有select的权限。原因是当在单个数据库上赋予权限时,权限会合并;但是在多个数据库上赋予权限时,每个数据库都会认为是单独的一组权限,当用revoke all 的时候并不起作用,只能对当个数据库回收权限
-
确保socket也是安全的,不放在默认的/tmp/,以防止有意无意的删除
网络层面:
数据库应尽量放在局域网中。
代码层面
注意sql注入,sql注入即攻击者利用sql解析器原理,程序校验的缺陷。通过程序输入非法数据达到入侵目的