[聚合文章] SQL Server 安全篇——数据层面安全性(3)——模拟(Impersonation)

SQL Server 2018-01-26 18 阅读

接上文: SQL Server 安全篇——数据层面安全性(2)——所有权链接( Ownership Chaining)

模拟是指在不同安全主体的上下文下执行T-SQL语句或代码模块的做法。用来最小化权限授予和授予权限的用户数,但是不影响执行时提升到所需的权限。实际上,在会话或模块的执行期间,模拟起到了用户或登录名切换的过程。也可以不严谨地认为,发起模拟的用户A借用B的身份执行了B有权限但A没权限做的事。

在SQL Server中,可以使用EXECUTE AS子句来实现模拟功能。EXECUTE AS可以位于存储过、函数、DML触发器的头部。也可以用于会话过程切换安全上下文。下表是EXECUTE AS可用场景:

用处 上下文规范(Context Specification)
Session(会话)
  • LOGING
  • USER
存储过程、函数、DML触发器
  • CALLER
  • SELF
  • OWNER
  • USER
库级别DDL触发器
  • CALLER
  • SELF
  • USER
服务器级别DDL触发器
  • CALLER
  • SELF
  • LOGIN
Queues(队列)
  • CALLER
  • SELF
  • USER

上下文规范(Context Specification)说明

  • CALLER:意味着代码运行在原始上下文,是除队列之外的默认行为。
  • SELF:代码在创建或最后更改模块的主体的上下文下执行。
  • OWNER:代码运行在安全主体的拥有者上下文。
  • USER:以数据库特定用户运行代码。
  • LOGIN:以特定登录名来运行代码。

下面来演示一下,首先创建一个登录名George:

USE master 
GO 
CREATE LOGIN George 
WITH PASSWORD='强密码', 
DEFAULT_DATABASE=master, CHECK_EXPIRATION=OFF, CHECK_POLICY=ON ; 
GO
然后在演示库创建一个用户,关联这个登录名:
USE AdventureWorks2016 
GO 
CREATE USER George FOR LOGIN George

然后调用不带参数的SUSER_SNAME()函数返回当前安全上下文的登录名(注意这里不能是“组”或者“绝色”,必须是单一账号):

USE AdventureWorks2016
GO
--以当前上下文运行
SELECT SUSER_SNAME() ; 
--转换当前上下文为George用户 
EXECUTE AS USER = 'George' ; 
--再次查询
SELECT SUSER_NAME() ;

结果如图:

第一个查询运行在我自己的登录名的安全上下文中,当执行完EXECUTE AS语句之后,上下文切换成George,但是注意除非你关掉这个界面,不然需要使用REVERT命令来恢复上下文,否则将一直以George的上下文来运行。

准确来说,在下面情况发生之前,切换后的上下文一直有效:

  1. 运行另一个Execute AS语句
  2. 运行REVERT语句
  3. 删除会话(比如SSMS关闭查询窗口)
  4. 存储过程或触发器中的命令执行了退出操作。

注意:对于即席查询(ad hoc SQL)的EXECUTE AS子句,必须在安全上下文中具有模拟权限,否则使用EXECUTE AS也会报错。另外,非包含数据库或SQL DB(Azure上)之外的模拟,其执行返回限制于服务器级别。

最佳实践:

首先当然还是要维持最低所需权限。比如只需要DB级别的就不要给Server级别的权限。当需要在一个过程中切换多次登录时(不建议),要保持原始登录的识别,以免后续忘记切回去,这个原始登录可以通过ORIGINAL_LOGIN函数来获取。

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。