【问题标题】:SQL Server: EXECUTE AS clause of stored procedure not granting sysadmin permissionsSQL Server:存储过程的 EXECUTE AS 子句未授予系统管理员权限
【发布时间】:2014-12-23 07:49:20
【问题描述】:

我开发了一个存储过程,以便从备份文件恢复数据库并向其中添加应用程序用户。此存储过程属于 master 数据库。

问题是我的 IT 部门不允许我使用 admin 用户,只能对 sysadmin 用户使用 EXECUTE AS 语句。

我可以恢复数据库,但我找不到在进程结束时添加用户的方法。

我使用的代码:

CREATE PROCEDURE [dbo].[myProc] 
@database VARCHAR(50)
WITH EXECUTE AS 'aSysAdminUser' 
AS
BEGIN
    --Restore the database (working)
    --Add the application user    (not working)                  
    SET @sqlScript = 'USE '+@database +';
    CREATE USER [myApplicationUser] FROM LOGIN [myApplicationUser];
    EXEC sp_addrolemember ''db_owner'', ''myApplicationUser'''
    EXEC(@sqlScript)
END

当我运行它时,我收到以下错误消息:

服务器主体“aSysAdminUser”无法 在当前安全上下文下访问数据库“数据库”。

知道如何使用 EXECUTE AS 语句从主数据库上的存储过程中以动态参数数据库名称创建用户吗?

谢谢

【问题讨论】:

  • WITH EXECUTE AS 'dbo' ?
  • 问题与模拟(即EXECUTE AS)及其局限性有关。我现在正在寻找答案。 PS。他们在审查这个过程吗?您不能通过 SQL 注入授予自己“系统管理员”服务器角色吗? ;-)。
  • 其实,没有。我只是尝试创建登录,但它不起作用。而且我几乎可以肯定,出于同样的原因,这个脚本不能按预期工作。等等。
  • 我的 IT 部门不想将 sysadmin 授予任何人,只是允许我们执行 EXECUTE AS。感谢您的帮助

标签: sql-server permissions sql-server-2008-r2 impersonation database-permissions


【解决方案1】:

您面临的问题是模拟的限制(即通过EXECUTE AS 切换安全上下文)。对于数据库范围的对象,例如存储过程,您在EXECUTE AS 子句中指定数据库级别的user,而不是服务器级别的login。因此,这个过程并不是真正充当sysadmin。但是,有一种方法可以安全地授予仅此一个存储过程真正的sysadmin 权限,这将允许它执行动态 SQL 中的步骤,即:

  1. 连接到数据库
  2. 创建用户
  3. 改变角色

执行此操作的方法是使用证书对存储过程进行签名。然后该证书还将用于创建将添加到sysadmin 服务器角色的服务器级登录。然后,当任何用户/登录名(对这个存储过程有EXECUTE权限)执行这个过程时,它只会通过相同的证书签名来获取基于证书的登录权限。

第一步:[master]数据库中设置证书:

USE [master];
GO

CREATE CERTIFICATE [BackupRestoreCert]
    ENCRYPTION BY PASSWORD = N'MyPassword'
    WITH SUBJECT = N'Certificate for Managing Backup/Restore Operation Permissions';
GO

第 2 步: 创建登录并添加到sysadmin 角色:

CREATE LOGIN [BackupRestoreOps] FROM CERTIFICATE [BackupRestoreCert];

ALTER SERVER ROLE [sysadmin] ADD MEMBER [BackupRestoreOps];

第 3 步:使用该证书对存储过程进行签名,创建指向新登录名的链接:

ADD SIGNATURE
    TO [dbo].[myProc]
    BY CERTIFICATE [BackupRestoreCert]
    WITH PASSWORD = 'MyPassword';

以上所有内容实际上都是在[master] 数据库的上下文中完成的,尽管将其分解似乎更易于解释。但是,在实践中,这将是 IT 人员运行一次的单个脚本。当然,如果您曾经 ALTER 那个存储过程,他们将不得不再次运行 ADD SIGNATURE 命令(即第 3 步),因为该过程的定义发生任何更改都会丢失。

就是这样。我已经使用问题中显示的存储过程对此进行了测试,并且确实如此,一旦我添加了签名和sysadmin 角色,创建用户并将其添加到db_owner 角色。

第 4 步(可能):您可能可以从存储过程中删除 EXECUTE AS 子句。如果它确实传递了任何允许初始还原操作工作的权限,那么现在应该通过基于证书的登录来假定这些权限,因为它被标记为sysadmin


免责声明
我只是想/需要明确一点,考虑到问题中指定的存储过程,正如它所写的那样,一旦授予此权限,允许 SQL 注入。当然,这已经是 IT 人员决定使用EXECUTE AS 子句授予此存储过程的sysadmin 权限的初衷的结果。我现在只是指出,上述步骤实际上将使他们的预期行为成为现实。如果动态 SQL 上方的步骤在传入数据库名称以外的任何内容时会出错,那很好,但是对于可能希望复制此内容并只是复制/粘贴而不了解完整内容的其他人,仍然需要说明这一点上下文。

应该做两件事:

  1. 虽然是小问题,但输入参数的数据类型应为 sysnameNVARCHAR(128) 的别名),因为 [name][sys].[databases] 中是这样定义的。
  2. 要做的主要事情是验证传入的值是一个现有的数据库名称,类似于:

    IF (DB_NAME(@database) IS NULL)
    BEGIN
       RAISERROR(N'Invalid Database Name', 16, 1);
       RETURN;
    END;
    

编辑:
我试图找到另一个允许这个不是sysadmin 的服务器角色,希望不使用这样的特权角色。我试过dbcreatorsecurityadminserveradminsetupadmin,但不幸的是它们都没有工作:(。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    • 2012-07-12
    • 1970-01-01
    • 2018-11-20
    • 2010-09-30
    • 2015-06-19
    相关资源
    最近更新 更多