1、前言
- 对于任何一个企业来讲,其数据库系统中所保存数据的安全性无疑是很是重要的,尤为是公司的有些商业数据,可能数据就是公司的根本。
- 失去了数据,可能就失去了一切
- 本章将针对mysql的安全相关内容进行较为详细的介绍。
2、数据库系统安全相关因素
一、外围网络
让咱们的mysql处在一个有保护的局域网之中,而不是置于开发的公网中。mysql
二、主机
第二层防线“主机层防线”,“主机层防线“主要拦截网络(包括局域网)或者直连的未受权用户试图入侵主机的行为。sql
三、数据库
第三道防线“数据库防线”,也就是mysql数据库系统自身的访问控制受权管理相关模块。数据库
这道防线基本上能够说是mysql的最后一道防线了,也是最核心最重要的防线。安全
以前的两层防线对于全部数据库系统来讲基本上区别不大,都存在者基本相同的各类威胁,不管是Oracle仍是mysql,以及其余的数据库管理系统,都须要基本一致的“布防”策略。网络
可是这第三层防线,也就是各自自身的“数据库防线”对于每一个数据库系统来讲都存在较大差别,由于每种数据库都有各自不太同样的专门负责访问受权相关的模块。不管是权限划分仍是实现方式均可能不太同样。函数
MySql的访问受权相关模块主要是由两部分组成,一个是基本的用户管理模块;另外一个是访问受权控制模块。工具
- 用户管理模块相对简单,主要是负责用户登录链接相关的基本权限控制,但其在安全控制方面的做用不比任何环节小。他就像mysql的一个“大门门卫”同样,经过校验每一位敲门者所给的进门“暗号”(登入口令),决定是非给敲门者开门。
- 访问控制模块则是随时随地检查已经进门的访问者,校验他们是否有访问所发出请求须要访问的数据的权限。经过校验者能够顺利拿到数据,而未经过校验的访问者,只能收到“访问越权”的相关反馈。
四、代码
1)SQL语句相关安全因素
“SQL注入攻击”指的就是攻击者根据数据库的SQL语句解析器的原理,利用程序中对客户端所提交数据的校验漏洞,从而经过程序动态提交数据接口提交非法数据,达到攻击者的入侵目的。性能
“SQL注入攻击“的破坏性很是大,轻者形成数据被窃取,重者数据遭到破坏,甚至可能丢失所有的数据。加密
2)程序代码相关安全因素
程序代码若是权限校验不够仔细而存在安全漏洞,则一样可能会被入侵者利用,达到窃取数据等目的。spa
好比一个存在安全漏洞的信息管理系统,很容易就可能窃取到其余一些系统的登入口令。以后,就能冠冕堂皇的轻松登录到其余相关系统达到窃取相关数据的目的。甚至还可能经过应用系统中保存不善的数据库系统链接登录口令,从而带来更大的损失。
3、MySQL权限系统介绍
一、权限系统简介
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
- Global Level的权限控制也叫全局权限控制,全部权限信息都保存在mysql.user表中。
- Global Level的全部权限都是针对整个mysqld的,对全部的数据库下的全部表及全部字段都有效。
- 若是一个权限是以Global Level来授予的,则会覆盖其余全部级别的相同权限设置。
- 好比咱们首先给abc用户受权能够update指定数据库如test的t表,而后又在全局级别REVOKE掉了abc用户对全部数据库的全部表的UPDATE权限,那么这时候的abc用户将再也不拥有对test.t表的更新权限。
- 要授予Global Level的权限,则只须要在执行GRANT命令的时候,用“*.*”来指定适用范围是Global的便可,当有多个权限须要授予的时候,也并不须要屡次重复执行GRANT命令,只须要一次将全部须要的权限名称经过逗号(“,”)隔开便可,如:GRANT SELECT,UPDATE,DELETE,INSERT ON *.* TO 'def'@'localhost';
2)Database Level
- Database Level是在Global Level之下,其余三个Level之上的权限级别,其做用域即为所指定整个数据库中的全部对象。
- 与Global Level相比,Database Level主要少了如下几个权限:CREATE USER、FILE、PROCESS、RELOAD、REPLICATION CLIENT、REPLICATION SLAVE、SHOW DATABASES、SHUTDOWN、SUPER和USAGE这几个权限,没有增长任何权限。
- 以前咱们说Global Level的权限会覆盖底下其余四层的相同权限,Database Level也同样,虽然他可能被Global Level的权限所覆盖,但同时他也能覆盖比他更下层的Table、Column和Routine这三层的权限。
- 若是要授予Database Level的权限,则能够有两种实现方式:
a.在执行GRANT命令的时候,经过“database.*”来限定权限做用域为database整个数据库:GRANT ALTER ON test.* TO 'def'@'localhost';
b.先经过USE命令选定须要受权的数据库,而后经过“*”来限定做用域,这样受权的做用域实际上就是当前选定的数据库
- 在授予权限的时候,若是有相同的权限须要授予多个用户,咱们也能够在受权语句中一次写上多个用户信息,用逗号分隔开就能够了,如:grant create on perf.* to 'abc'@'localhost','def'@'localhost';
3)Table Level
- Database Level之下就是Table Level的权限了,Table Level的权限能够被Global Level 和Database Level的权限所覆盖,同时也能覆盖Column Level 和Routine Level 的权限。
- Table Level 的权限做用范围是受权语句中所指定数据库的指定表。如能够经过以下语句给test数据库的t1表受权:GRANT INDEX ON test.t1 TO 'abc'@'%.jianzhaoyang.com';
- Table Level的权限因为其做用域仅限于某个特定的表,因此权限种类也比较少,仅有ALTER、CREATE、DELETE、DROP、INDEX、INSERT、SELECT、UPDATE这八种权限。
4)Column Level
- Column Level的权限做用范围就更小了,仅仅是某个表的指定的某个列。
- 因为权限覆盖的原则,Column Level的权限一样能够被Global、Database、Table这三个级别的权限中的相同级别所覆盖,并且因为Column Level所针对的权限和Routine Level的权限做用域没有重合部分,因此不会有覆盖与被覆盖的关系。
- Column Level的权限只有INSERT、SELECT和UPDATE这三种。
- Column Level的权限受权语句语法基本和Table Level差很少,只是须要在权限名称后面将须要受权的列名列表经过括号括起来:GRANT SELECT(id,value) ON test.t2 TO 'abc'@'%.jianzhaoyang.com';
- 当某个用户在向某个表插入数据的时候,若是该用户在该表中某列上面没有INSERT权限,则该列的数据将以默认值填充。这一点和不少其余的数据库有一些区别,是mysql本身在SQL上面的扩展。
5)Routine Level
- Routine Level的权限主要只有EXECUTE和ALTER ROUTINE两种,主要的针对的对象是procedure 和function这两种对象。
- 在授予Routine Level权限的时候,须要指定数据库和相关对象,如:GRANT EXECUTE ON test.p1 to 'abc'@'localhost';
6)GRANT权限
- 除了上述几类权限外,还有一个很是特殊的权限GRANT,拥有GRANT权限的用户能够将自身所拥有的任何权限所有授予其余任何用户,因此GRANT权限是一个很是特殊也很是重要的权限。
- GRANT权限的授予方式也和其余任何权限都不太同样。
- 一般是经过在执行GRANT受权语句的时候在最后添加WITH GRANT OPTION子句达到授予GRANT权限的目的。
- 另外,咱们还能够经过GRANT ALL语句授予某个Level的全部可用权限给某个用户,如: grant all on test.t5 to 'abc';
- 以上五个Level的权限中,Table、Column和Routine三者在受权中所依赖(或引用的)对象必须是已经存在的,而不像Database Level的权限授予,能够在当前不存在该数据库的时候完成受权。
四、MySQL访问控制实现原理
- MySQL的访问控制实际上由两个功能模块共同组成,一个是负责“看守mysql大门”的用户管理模块,另外一个就是负责监控来访者每个动做的访问控制模块。
- 用户管理模块决定造访客人可否进门,而访问控制模块则决定每一个客人进门能拿什么不能拿什么。
- mysql中实现简单访问控制的流程图以下:
-
用户管理:
(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在权限校验过程当中,只要找到匹配的权限以后,就不会再继续日后查找是否还有匹配的权限信息,而直接完成校验过程。
4、MySQL访问受权策略
一、前言
- 在咱们了解了数据库系统安全的相关因素和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权限。
5、安全设置注意事项
- 使用私有局域网。咱们能够经过使用私有局域网,经过网络设备,统一私有局域网的出口,并经过网络防火墙设备控制出口的安全。
- 使用SSL加密通道。若是咱们对数据保密要求很是严格,能够启用mysql提供的ssl访问接口,将传输数据进行加密。使网络传输的数据即便被截获,也没法轻易使用。
- 访问受权限定来访主机信息。咱们能够在受权的时候,经过指定主机的主机名、域名或IP地址信息来限定来访主机的范围。
- OS安全方面。关闭mysql Server主机上面任何不须要的服务,这不只能从安全方面减小潜在隐患,还能减小主机的部分负担,尽量提升性能。
- 使用网络扫描工具(如nmap等)扫描主机端口,检查除了mysql须要监听的端口3306以外,还有哪些端口是打开正在监听的,并去没必要要的端口。
- 严格控制OS帐号的管理,以防帐号信息外泄,尤为是root和mysql帐号。
- 对root和mysql等对mysql的相关文件有特殊操做权限的OS帐号登录后作出比较显眼的提示,并在Terminal的提示信息中输出当前用户信息,以防止操做的时候通过屡次用户切换后出现人为误操做。
- 用非root用户运行mysql。由于若是使用root运行mysql,那么myslqd的进程就会拥有root用户所拥有的权限,任何具备FILE权限的用户就能够在mysql中向系统中的任何位置写入文件。
- 文件和进程安全。合理设置文件的权限属性,mysql的相关数据和日志和所在文件夹属主和所属组都设置为mysql,且禁用其余全部用户的读写权限。以防止数据或者日志文件被窃取或破坏。
- 确保mysql server所在的主机上所必要运行的其余应用或服务足够安全,避免由于其余应用或者服务存在安全漏洞而被入侵者攻破防线。
- 用户设置。咱们必须确保任何能够访问数据库的用户都有一个比较复杂的内容做为密码,而不是很是简单或者比较有规律的字符,以防止被使用字典破解程序攻破。
- 在 MySQL初始安装完成以后,系统中可能存在一个不须要任何密码的root用户,有些版本安装完成以后还会存在一个能够经过localhost登陆的没有用户名和密码的账号。这些账号会给系统带来极大的安全隐患,因此咱们必须在正式启用以前尽早删除,或者设置一个比较安全的密码。
- 对于密码数据的存放,也不要存放在简单的文本文件之中,而应该使用专业密码管理软件来管理(如KeePass)。
- 安全参数。不须要使用的功能模块尽可能都不要启用。例如,若是不须要使用用户自定义函数,就不要在启动的时候使用“--allow-suspicious-udfs”参数选项,以防止被别有居心的潜在威胁者利用此功能而对MySQL的安全形成威胁;
- 不须要从本地文件中Load数据到数据库中,就使用“--local-infile=0”禁用掉能够从客户端机器上Load文件到数据库中