等保测评2.0:SQLServer访问控制(上)

2020-04-10 271820人围观 ,发现 3 个不明物体 数据安全标准与合规

一、前言

本篇文章主要说一说SQLServer数据库中访问控制控制点涉及到的SQLServer基础知识,本来想和对测评项的理解写在一起的,但是发现这样篇幅过长,且SQLServer的权限结构有点绕,不利于阅读和吸收,所以就分开来写了(写完之后我自己都有点晕了)。

对于SQLServer的权限管理,我从接触初始就感觉到迷惑,登录名、服务器角色我懂,但是数据库用户是用来干嘛的?架构又是用来干嘛的?数据库角色和架构是重名的,有什么特殊关系吗?权限到底是如何传递、判断的?用户的默认架构又是怎么回事……

趁着春节假期,花时间把这些东西从头到尾捋了捋,希望对大家能够有所帮助。

二、SQLServer的权限分配

先对SQLServer的权限分配进行基本介绍,如果对这个不清楚的话,那么访问控制控制点的测评实际上也没办法进行。

2.1. 基本概念

SQLServer在权限方面的构造有一点点绕,容易迷惑人,要从基本的概念说起。

涉及到SQLServer权限的有登录名、服务器角色、数据库用户、数据库角色、架构等。

注意,该文章可能比较枯燥,但比较实用,网上其它文章虽然写得深入得多,但是未必这么详细。

2.2. 登录名

登录名也就是一般意义上的账户,包括SQLServer中的账户和Windows操作系统登录名:

使用登录名登录之后,才可以访问数据库实例。

2.3. 服务器角色

角色大家都知道,即一系列权限的**,而拥有角色的账户,也就拥有了这一系列的权限。

而SQLServer的服务器角色,顾名思义,也就是服务器级别的角色,对该服务器的所有数据库均具备权限。

其具体角色和权限如下:

在SQLServer这里,服务器角色的拥有者只能是登录名,右键点击某一服务器角色,选择属性,在角色成员列表下方点击添加,在弹出来的窗口中选择对象类型,我们会发现只存在登录名这一对象类型:

另外,服务器角色中的角色是固定的,不能创建和删除(不存在该选项):

服务器角色的权限,除了public以外,也都是固定的:

将登录名添加到服务器的角色成员(即拥有该角色的权限),可以在服务器角色的属性中添加(如上文所展示的),也可以在登录名的属性中添加:

这里要注意的是,public是一个特殊的服务器角色,所有登录名默认拥有该角色,且不可更改(即强制拥有public角色的权限)。

那么,对public赋予过多的权限,就意味着权限失控。

public的默认权限为VIEW ANY DATABASE,网上的文章都这么说,这是对的。

但是你真的跑去查看public的权限时,是看不到这个权限的:

实际上需要在安全对象中添加当前服务器,才能看到该权限和进行设置:

好,服务器角色的介绍先到此为止。

其实服务器角色这个层面的话,是比较容易理解的,因为它就是用户-角色-权限的常见模型。

2.4. 架构

先来说架构,架构包含数据库对象,如表、视图和存储过程,可以理解为数据库对象的**。

上面是一种描述,其直观的体现为是数据库表的名字,从SQLServer2005开始,一个数据库表的完全限定名称为,server.database.schema.object也就是服务器.数据库.架构.对象。

我这里创建了一个数据库,名为TestDB,其默认存在的架构如下(T1是我自己创建的):

在创建数据库表的时候,就要给它指定一个架构,可以是默认的架构,也可以是自己创建的架构:

这里我选择了架构T1,一般默认选择的架构是dbo。

好,架构说到这里,大家记住,某数据库表属于某架构。

2.5. 数据库角色

每个数据库都拥有自己的角色,为数据库级别的角色,如下图:

首先,数据库角色也是拥有一定的权限的,不过是数据库级别的权限:

数据库角色中可以自创角色,但是默认存在的数据库角色除了public以外,其它角色的直接权限不可更改。

数据库角色public和服务器角色public有些类似,在数据库一级,所有(数据库)用户均属于public角色。

大家注意看,数据库角色和架构中有很多是重名的:

其实它们没有什么特殊的关系,只是在默认情况下,比如角色db_owner,默认为架构db_owner的拥有者而已,你也可以将架构db_owner的拥有者改成其他的数据库用户或者数据库角色:

那么拥有某架构是什么意思呢?拥有某架构其实就代表拥有了这个架构下数据库对象(比如数据库表)的所有权限。

但是架构的拥有者只能是某一个数据库角色或者某一个数据库用户,但可以实现间接拥有。

比如角色A拥有架构B,数据库用户C属于角色A,那么数据库用户C也拥有架构B。

2.6. 数据库用户

每个数据库都拥有自己的用户,是数据库级别的,如下图:

数据库用户是用来干啥的呢?

它是用来承上启下的,登录名不能直接访问数据库对象,它需要和被访问数据库的数据库用户进行映射,然后使用数据库用户的权限来进行操作:

三、权限分配实际例子

理论说得多没有用,还是用实际的例子来说,一看就明白了。

存在登录名TestLogin,存在数据库TestDB,数据库中的数据库用户为默认用户,数据库中存在数据库表TestTable,数据库表的架构为T1,其拥有者为数据库用户dbo,服务器角色public权限为默认权限,数据库角色public的权限为默认权限。

登录TestLogin,此时由于TestDB中仅存在默认数据库用户,TestLogin无映射的数据库用户,无法访问TestDB。

注:实际映射了guest用户,但guest用户现在无权限,guest用户的内容在数据库默认用户中进行说明。

创建TestDB的数据库用户TestUser,映射TestLogin,TestUser此时不拥有任何架构,不属于任何角色:

此时TestUser默认属于数据库角色public,拥有一定的权限,但是对于TestTable表不具备任何权限:

数据库角色Public对于TestTable表无任何权限:

对于其它视图具备选择权限:

此时直接查询TestTable,会显示权限不足:

下面说明获得权限的几种方法,以查询权限为例。

3.1. 方法一

在服务器角色层面获得权限

比如将sysadmin授予TestLogin登录名:

此时,由于sysadmin具备所有权限,TestLogin自然就获得了查询权限:

注:这里比较特殊,属于sysadmin的登录名会映射到每个数据库内的dbo用户(该属于数据库的db_owner角色),所以此处和TestUser没啥关系,如果不存在TestUser,但只要TestLogin属于sysadmin,TestLogin仍具备权限。这部分具体内容在数据库默认用户中说明。

这里也可以给服务器角色public设置相应权限(如控制服务器权限),使得TestLogin获得相应权限。

3.2. 方法二

在数据库角色层面获得权限

将TestLogin从sysadmin中移除,将数据库角色db_datareader赋予TestUser:

由于db_datareader的权限为从所有用户表中读取所有数据,故TestUser获得了查询权限。

这里是因为TestUser获得了数据库级别的读取权限:

这里也可以让数据库角色public设置相应权限,使得TestUser获得相应权限。

3.3. 方法三

直接拥有某架构,从而获得架构的权限

将TestUser从db_datareader中移除,再将架构T1的所有者改为TestUser:

则此时TestUser拥有了T1架构的全部权限,自然就拥有了查询权限:

3.4. 方法四

间接拥有某架构,从而获得架构的权限

将T1的所有者改为db_datawriter,再将db_datawriter赋予TestUser,则相当于TestUser间接拥有了T1架构,也就拥有了查询权限:

注意,这里和db_datawriter本身的权限无关,db_datawriter为写的权限,如果此处不是TestUser间接拥有了T1架构,仅仅是获得了db_datawriter的权限,则不可能具备查询权限。

这里也可以让数据库角色public拥有T1,则TestUser会间接拥有了T1架构。

3.5. 方法五

获取表级权限

先进行重置:将T1的所有者改回数据库用户dbo,再将TestUser从db_datawriter中移除。

在数据库表的属性中可直接对数据库用户或数据库角色public进行权限设置:

这里对TestUser的权限进行设置,授予其选择权限,其中有效选项卡中即为其权限,列字段代表涉及到的数据库列(TestTable只有一个列test):

则此时,TestUser具备了TestTable的查询权限。

这里的权限,可以在数据库表的属性中进行设置,也可以在TestUser的属性中进行设置,是同一个意思:

注意:上图中授予和拒绝的选项框是互斥的。

3.6. 方法六

直接获取架构级的权限

还可以在架构级进行权限,其实和表级权限是一样的,也是在架构的属性或者数据库用户的属性中进行设置:

这里有一个优先级和权限传递的关系。

比如我在T1架构处赋予了TestUser选择权限,则取查看TestTable属性时,其显示选项卡虽然不会有任何变化:

但是其有效选项卡会显示实际具备的权限,TestUser具备对TestTable的查询权限:

如果是T1处将选择权限设置为拒绝,那么在TestTable处将选择权限设置为授予也没啥用,TestUser照样不具备对TestTable的选择权限。

又或者,T1处将选择权限设置为授予,在TestTable处将选择权限设置为拒绝,TestUser仍然不具备对TestTable的选择权限。

所以,SQLServer的权限判断模式,应该是从上至下,一级一级的判断,其中任何一级只要设置了拒绝,那么对于某对象就不具备该权限。

如果表具备多列的话,还可以设置列级权限:

上图中,TestTable增加了test2列,将test列的选择权限设置为拒绝。

则最后的权限为:

实际查询时返回错误如下:

3.7. 方法七

直接获取数据库级的权限

数据库级别的权限设置,在数据库的属性中,可以设置数据库级别的权限:

TestUser默认具备的权限是连接,那么这个和成为数据库角色的成员再获得权限有啥区别呢?

应该没啥区别,仅仅是SQLServer支持这两种权限设置的方式而已。

一种是直接将单个权限授予给数据库用户,一种是通过角色来间接授予权限。

3.8. 方法八

直接获取服务器级的权限

服务器级别的权限设置,服务器属性中也可以进行单项权限的设置:

3.9. 方法九

直接拥有某数据库,从而获得数据库的权限

数据库的拥有者只能是登录名,且其拥有者即为数据库用户dbo映射的登录名,默认情况下,该登录名为sa。

可以在数据库属性中对其拥有者进行更改:

此时,数据库用户dbo映射的登录名也将会变成TestLogin:

数据库dbo用户默认属于db_owner角色,且不可撤销:

所以,TestLogin也就自然获得了权限。

四、默认数据库用户

在创建一个数据库后,会默认存在dbo、guest、INFORMATION_SCHEMA、sys账户:

4.1. dbo用户

dbo的全程应该是:database owner,即数据库所有者。

其默认映射的登录名为sa,其属于的数据库角色为db_onwer:

其属于的数据库角色不可改变,其映射的登录名可以在数据库属性中进行更改:

dbo用户可以属于多个登录名(但是不会在数据库用户属性中显示出来):属于sysadmin服务器角色的登录名会直接映射到每个数据库内的dbo用户。

4.2. guest用户

guest用户默认应该没有权限,或者顶多默认具有连接权限。

当一个登录名在某一个数据库中没有映射的数据库用户时,将会映射到guest用户中,具备guest用户的权限。

比如TestLogin如果在TestDB中不具备映射的数据库用户时,它将映射到guest用户中,此时若guest用户属于db_onwer数据库角色,那么TestLogin也获得相关权限。

当一个登录名在某一个数据库中存在映射的数据库用户时,就不会映射到guest用户中了,也不会具备guest用户的权限。

比如TestLogin如果在TestDB中存在一个映射的数据库用户TestUser,此时就与guest用户无关了,guest用户属于db_onwer数据库角色,TestLogin也不会具备相关权限。

在登录名的属性中,可以看到某个数据库的guest用户是否被启用:

注意,这里的所谓启用还是不启用,仅仅是指在数据库属性中,是否赋予了guest用户连接属性。

如果在数据库属性中赋予了,此处的选项框就会被勾选。

而且好像仅仅只认同这一个方式的权限赋予,比如在guest用户属性中,将guest用户添加为db_onwer的成员,此时guest用户已经具备了数据库的所有权限。

但是在这里的选项框处,仍然不会显示被勾选。

4.3. 其他默认账户

也就是information_schema、sys,这两个默认用户拥有两个默认框架information_schema、sys,这两个默认框架包含内容如下:

但是这两个用户到底映射哪些登录名,我是真没搞明白……

五、应用程序角色

这个还是单独说吧,在数据库内可以创建应用程序角色:

可以看到,应有程序角色不包括成员,且需要设置密码。

应用程序角色说明如下:

Microsoft® SQL Server™ 中的安全系统在最低级别,即数据库本身上实现。无论使用什么应用程序与 SQL Server 通讯,这都是控制用户活动的最佳方法。但是,有时必须自定义安全控制以适应个别应用程序的特殊需要,尤其是当处理复杂数据库和含有大表的数据库时。

此外,可能希望限制用户只能通过特定应用程序(例如使用 SQL 查询分析器或 Microsoft Excel)来访问数据或防止用户直接访问数据。限制用户的这种访问方式将禁止用户使用应用程序(如 SQL 查询分析器)连接到 SQL Server 实例并执行编写质量差的查询,以免对整个服务器的性能造成负面影响。

其特征如下(在 SQL Server 中创建应用程序角色):

使用应用程序的方法:sp_setapprole (Transact-SQL)

其余的就不进行更多说明了,因为在SQLServer中进行权限设置的人本来就不多,使用应用程序角色这个功能的人就更少了。

六、其他说明

6.1. 数据库角色的所有者

数据库角色有一个所有者属性,这个属性不知道有什么用。

在默认状态下,将db_owner的所有者改为TestUser,TestUser不会具备db_owner的权限:

6.2. 默认架构

另外,TestLogin登录名会的属性中,有一个默认架构:

这个默认架构也不会赋予登录名或数据库用户什么权限,仅仅是在执行SQL语句时,如果涉及到该数据库的具体表名时,会自动给你加上(默认架构)前缀而已。

比如TestTable属于T1架构,由于TestUser的默认架构是dbo,所以直接执行下述SQL语句,会显示这样的错误:

需要手动加上前缀:

如果将TestUser的默认架构改成T1,也就不用手动加前缀了:

6.3. 重名

在SQLServer的权限结构中,会出现很多重名现象,比如架构和数据库角色的重名上面已经说过了,还存在着架构和数据库用户的重名。

比如:

不过dbo架构无法修改所有者,强制为dbo用户,仅此而已。

6.4. 版本差异

在2000中,假如有一个账户tt在test数据库中创建了一张表table1的时候,在服务器上对查询的语句应为select * from test.tt.table1,也就是说,在sqlserver 2000中一张表所属的架构默认就是表的创建者的登录名称,用户可以和修改他所创建的所有数据库对象。

在 SQL Server 2005 中,架构和创建它的数据库用户不再关联,完全限定名(fully-qualified name)现在包含4个部分:server.database.schema.object

另外,对于服务器角色public,如果在SQLServer 2005上面没有发现的话,那么很可能是因为你没有安装sql server的补丁包(sql server 2005 sp2)。

七、总结

通篇写下来,好像SQLServer的权限结构和其它数据库没多少区别。

但是SQLServer数据库在中间搞了个数据库用户,而且又存在大量的重名现象,很容易把人搞晕了。

下面做了个简图,大概的描述了下权限结构:

SQLServer的权限判断模式,应该是从上至下,一级一级的判断,其中任何一级只要设置了拒绝,那么对于某对象就不具备该权限。但对属于sysadmin的成员不做任何权限判断,换句话说,sysadmin组的成员可以为所欲为。

SQLServer可以控制到数据库表中列一级的权限。

SQLServer所有登录名均为服务器角色public的成员,所有数据库用户默认为数据库角色public的成员。

SQLServer中所有属于sysadmin服务器角色的登录名会直接映射到每个数据库内的dbo用户。

SQLServer中对于某一个登录名而言,如果某个数据库中无映射的数据库用户,那么将会映射到数据库guest用户中。

最后,这里对于架构中的对象只说了数据库表,视图和存储过程没有说,但是它们的权限判断模式基本差不多,就不写了。

另外,我这篇文章也只是介绍了SQLServer权限结构的一部分(基础)内容,其余的大家根据需要自行去探索吧。

*本文作者:起于凡而非于凡,转载请注明来自FreeBuf.COM

相关推荐
Loading...

特别推荐

填写个人信息

姓名
电话
邮箱
公司
行业
职位
css.php