转载:https://www.cnblogs.com/shamo89/p/10013356.html
让我们的mysql处在一个有保护的局域网之中,而不是置于开发的公网中。
第二层防线“主机层防线”,“主机层防线“主要拦截网络(包括局域网)或者直连的未授权用户试图入侵主机的行为。
第三道防线“数据库防线”,也就是mysql数据库系统自身的访问控制授权管理相关模块。
这道防线基本上可以说是mysql的最后一道防线了,也是最核心最重要的防线。
之前的两层防线对于所有数据库系统来说基本上区别不大,都存在者基本相同的各种威胁,不论是Oracle还是mysql,以及其他的数据库管理系统,都需要基本一致的“布防”策略。
但是这第三层防线,也就是各自自身的“数据库防线”对于每个数据库系统来说都存在较大差异,因为每种数据库都有各自不太一样的专门负责访问授权相关的模块。不论是权限划分还是实现方式都可能不太一样。
MySql的访问授权相关模块主要是由两部分组成,一个是基本的用户管理模块;另一个是访问授权控制模块。
“SQL注入攻击”指的就是攻击者根据数据库的SQL语句解析器的原理,利用程序中对客户端所提交数据的校验漏洞,从而通过程序动态提交数据接口提交非法数据,达到攻击者的入侵目的。
“SQL注入攻击“的破坏性非常大,轻者造成数据被窃取,重者数据遭到破坏,甚至可能丢失全部的数据。
程序代码如果权限校验不够仔细而存在安全漏洞,则同样可能会被入侵者利用,达到窃取数据等目的。
比如一个存在安全漏洞的信息管理系统,很容易就可能窃取到其他一些系统的登入口令。之后,就能堂而皇之的轻松登陆到其他相关系统达到窃取相关数据的目的。甚至还可能通过应用系统中保存不善的数据库系统连接登陆口令,从而带来更大的损失。
msql的权限系统在实现上比较简单,相关权限信息主要存储在几个被称为grant tables的系统表中,即:mysql.User,mysql.db,mysql.Host,mysql.table_priv和mysql.column_priv。
由于权限信息数据量比较小,而且访问比较频繁,所以mysql在启动的时候,就会将所有的权限信息都load到内存中保存在几个特定的结构中。
所以才有了我们每次手工修改了权限相关的表之后,都需要执行“flush privileges”命令重新加载mysql的权限信息。
当然,如果我们通过grant、revoke或者drop user命令来修改相关权限,则不需要手工执行“flush privileges”命令,因为在使用grant等来修改系统表的同时,也会修改内存结构中的权限信息。
在mysql5.0.2或更高版本的时候,mysql还增加了CREATE USER命令,以此创建无任何特别权限(仅拥有初始USAGE权限)的用户,通过CREATE USER命令创建了新用户后,新用户的信息也会自动更新到内存结构中。
所以,建议读者一般情况下尽量使用GRANT、REVOKE、CREATE USER以及DROP USER命令来进行用户和权限的变更操作,尽量减少直接修改grant tables来实现用户和权限变更的操作。
要为某个用户授权,可以使用GRANT命令,要去除某个用户已有的权限则使用REVOKE命令。
当然除了这两个命令之外,还有一种比较暴力的办法,那就是直接更新grant tables系统表。
当给某个用户授权的时候,不仅需要指定用户名,同时还要指定来访主机。
如果授权的时候仅指定用户名,则mysql会自动认为是对“username@%”授权。
要去除某个用户的权限同样也需要指定来访主机。
可能有些时候我们还需要查看某个用户目前拥有的权限,这可以通过两个方式实现,首先是通过执行“show grants for 'username'@'hostname'”命令来获取之前该用户身上的所有授权。另一种方法是查询grant tables里边的权限信息。
1)Global Level
2)Database Level
3)Table Level
4)Column Level
5)Routine Level
6)GRANT权限
用户管理:
(1)在mysql中,用户访问控制部分的实现比较简单,所有授权用户都存放在一个系统表中:mysql.user,当然这个表不仅存放了授权用户的基本信息,还存放有部分细化的权限信息。
(2)用户管理模块需要使用的信息很少,主要就是Host、User、Password这三项,都在mysql.user表中
(3)一个用户想要访问mysql,至少需要提供上面列出的三项数据,mysql才能判断是否该让它进门。
(4)这三项实际是由两部分组成:来访者来源的主机名(或主机IP地址信息)和访问者的来访“暗号”(登陆用户名和登陆密码),这两部分中的任何一个没有能够匹配上都无法让看守大门的用户管理模块乖乖开门。
(5)其中Host信息存放的是mysql允许所对应的User的信任主机,可以是某个具体的主机名或域名,也可以是用“%”来充当通配符的某个域名集合,也可以是一个具体的IP地址,同样也可以是存在通配符的域名集合,还可以用“%”来代表任何主机,就是不对访问者的主机做任何限制。
访问控制:
(1)当客户端连接通过用户管理模块的验证,可连接上mysql server之后,就会发送各种Query和Command给mysql server,以实现客户端应用的各种功能。
(2)当mysql接收到客户端的请求之后,访问控制模块是需要校验该用户是否满足提交的请求所需要的权限。
(3)权限校验过程是从最大范围往最小范围的权限开始依次校验所涉及到的每个对象的每个权限。
(4)在验证所需权限的时候,mysql首先会查找存储在内存结构中的权限数据,首先查找Global Level权限,如果所需权限在Global Level都有定义(GRANT或REVOKE),则完成权限校验(通过或者拒绝);
(5)如果没有找到所有权限的定义,则会继续查找Database Level的权限,进行Global Level未定义的所需权限的校验,如果仍然没有找到所有所需权限的定义,则会继续往更小范围的权限定义域查找,也就是Table Level、Column Level或者Routine Level。
(6)在前面我们了解到mysql的grant tables有mysql.user、mysql.db、mysql.host、mysql.table_priv和mysql.column_priv这五个。
(7)我想除了mysql.host之外的四个都非常容易理解,每一个表都针对mysql的一种逻辑对象,存放某一特定Leve的权限,唯独mysql.host稍有区别。
(8)我们来看看mysql.host权限表在mysql访问控制中充当了什么样的角色?
【1】mysql.host在mysql访问控制模块中所实现的功能比较特殊,和其他几个grant tables不太一样。
【2】首先mysql.host中的权限数据不是通过GRANT或REVOKE来授予或者去除,而是必须手工通过INSESRT、UPDATE和DELETE命令来修改其中的数据。
【3】其次是其中的权限数据无法单独生效,必须通过和mysql.db权限表的数据一起才能生效。
【4】而且仅当mysql.db总存在不完整的时候,才会促使访问控制模块再结合mysql.host中查找是否有相应的补充权限数据实现以达到权限校验的目的。
【5】在mysql.db中无法找到满足权限校验的所有条件的数据,则说明在mysql.db中无法完成权限校验,所以也不会直接校验db.select_priv的值是否是Y。
(9)mysql的权限授予至少需要用户名和主机名二者才能确定一个访问者的权限。
(10)mysql如何确定权限信息?实际上,mysql永远优先考虑更精确范围的权限。
(11)在mysql内部会按照username和hostname做一个排序,对于相同username的权限,其host信息越接近访问者的来源host,则排序位置越靠前,则越早被校验使用到。
(12)而且mysql在权限校验过程中,只要找到匹配的权限之后,就不会再继续往后查找是否还有匹配的权限信息,而直接完成校验过程。
首先需要了解来访主机:
(1)由于mysql数据库登陆验证用户的时候是除了用户名和密码之外,还要验证来源主机,所以我们还需要了解每个用户可能从哪些主机发起连接。
(2)当然,我们也可以通过授权的时候直接通过“%”通配符来给所有主机授予都有访问的权限,但是这样就违背了我们安全策略的原则,带来了潜在风险,所以并不可取。
(3)尤其是在没有局域网防火墙保护的情况下,更是不能轻易允许可以从任何主机登陆的用户存在。
(4)能通过具体主机名和IP地址指定的尽量通过使用具体的主机名和IP地址来限定来访主机,不能用具体的主机名和IP地址限定的也需要用尽可能小的通配范围来限定。
其次,了解用户需求:
(1)既然要做到仅授予必要的权限,那么我们必须了解每个用户所担当的角色,也就是说,我们充分了解每个用户需要连接到数据库上完成什么工作。
(2)了解用户是一个只读应用的用户,还是一个读写都有的用户,是一个备份作业的用户还是一个日常管理的用户,是只需要访问特定的数据库,还是需要访问所有的数据库。
(3)只有了解了需要做什么,才能准确的了解需要授予什么样的权限。
(4)因为如果权限过低,会造成工作无法正常完成,而权限过高,则存在潜在的安全风险。
再次,要为工作分类:
(1)为了做到各司其职,我们需要将需要做的工作分门别类,不同类别的工作使用不同的用户,做好用户分离。
(2)虽然这样可能会带来管理成本方面的部分工作量增加,但是基于安全方面的考虑,这部分管理工作量的增加是非常值得的。
(3)而且我们所要做的分离也只是适度的分离。比如将执行备份工作、复制工作、常规应用访问、只读应用访问和日常管理工作分别分理出单独的特定账户来授予各自所需权限。
(4)这样,既可以让安全风险尽量降低,也可以让同类同级别的相似权限合并在一起,不互相交织在一起。
(5)对于PROCESS、FILE和SUPER这样的特殊权限,仅仅只有管理类账号才需要,不应该授予其他非管理账号。
最后,确保只有绝对必要者拥有GRANT OPTION权限:
(1)之前在权限系统介绍的时候我们已经了解到GRANT OPTION权限的特殊性,和拥有该权限之后的潜在风险,所以在这里就不赘述了。
(2)总之,为了安全考虑,拥有GRANT OTPION权限的用户越少越好,尽可能只让拥有超级权限的用户才拥有GRANT OPTION权限。