2009-12-08 75 views
1

我需要设置一个系统,该系统允许开发人员为数据库请求紧急ID。他们将被分配到一个名为“分析师”的角色,他将为他们提供一个下拉框,以及他们可以访问的数据库。他们将提交请求并生成临时SQL登录并显示在屏幕上。登录将有一些特权。登录将在12小时后被删除。请求临时登录的安全性

我已经把自己作为一个在ASP.net上的SA工作了,但现在我正在修改程序在应用程序连接字符串中使用SQL登录工作。

我试过几件东西让它工作,但碰到了路障。

这是我做的真正的工作。

USE [SQLEmergencyLoginRequest] 
GO 
/****** Object: StoredProcedure [dbo].[SQLELR_Login_CREATE] Script Date: 12/08/2009 14:48:29 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER PROCEDURE [dbo].[SQLELR_Login_CREATE] 
@SERVER VARCHAR(50), 
@DATABASE VARCHAR(50), 
@NTLOGIN VARCHAR(50), 
@IR INT, 
@LOGIN VARCHAR(50) OUTPUT, 
@PWD VARCHAR(20) OUTPUT, 
@NotifyDBA INT 
WITH EXECUTE AS OWNER 
AS 
/* 
Emergency_Access_Login_CREATE: Create Login/PWD, Create User, Create Role, Add User to Role, return Login/PWD. 
*/ 
DECLARE @Random_Login_Extension VARCHAR(20) 
DECLARE @sql VARCHAR(1000) 

SET @Database = QUOTENAME(@Database); 


BEGIN TRANSACTION 

--CREATE LOGIN/PWD 
EXEC dbo.random_password @Random_Login_Extension OUTPUT; 
EXEC dbo.random_password @PWD OUTPUT; 

SET @LOGIN = 'Emergency_Login_' + @Random_Login_Extension; 

SET @sql= 'CREATE LOGIN [' + @LOGIN + ']' + 
'WITH PASSWORD= ''' + @PWD + ''', DEFAULT_DATABASE=[master], ' + 
'CHECK_EXPIRATION=OFF, CHECK_POLICY=OFF'; 

EXEC(@sql); 

--CREATE USER 
DECLARE @User_Cmd VARCHAR(1000); 

SET @User_Cmd = 'USE ' + @DATABASE + ';' + 

'CREATE USER [' + @LOGIN + '] FOR LOGIN [' + @LOGIN + '];' + 
'EXEC sp_addrolemember N''db_datareader'',''' + @LOGIN + ''';' + 
'EXEC sp_addrolemember N''db_datawriter'',''' + @LOGIN + ''';' + 
'EXEC sp_addrolemember N''db_ddladmin'',''' + @LOGIN + ''';'; 

EXEC (@User_Cmd); 

INSERT INTO dbo.SQLELR_Emergency_Logins 
      ([CreationTime] 
      ,[NTLogin] 
      ,[IR] 
      ,[SERVER] 
      ,[DATABASE] 
      ,SQLLoginCreated) 
    VALUES 
      (GETDATE() 
      ,@NTLOGIN 
      ,@IR 
      ,@SERVER 
      ,@DATABASE 
      ,@LOGIN) 


DECLARE @MYBODY VARCHAR(500) 
SET @MYBODY = @NTLOGIN + ' has created a temporary login in the ' + @Database + ' Database. The login name is ' + @LOGIN; 

DECLARE @MYSUBJECT VARCHAR(500) 
SET @MYSUBJECT = 'Emergency Login Creation ON server ' + @@SERVERNAME; 

IF @NotifyDBA = 1 
BEGIN 
    EXEC msdb.dbo.sp_notify_operator 
     @profile_name = 'SQLDBA', 
     @name = 'SQLDBA', 
     @subject = @MYSUBJECT, 
     @body = @MYBODY; 
END 

COMMIT TRANSACTION 

我不想申请帐户在每一个DB高度特权,所以我创建了另一个帐户,这将进入每一个数据库,并有db_owner。很明显,使用固定数据库角色的sp_addrolemember需要db_owner才能工作,这就是为什么acct是db_owner。我更喜欢安全管理员,但似乎这是不可能的。

回到问题 - 使用EXECUTE AS和动态代码不起作用。

通过在创建用户的每个数据库中创建存储过程来完成此操作的唯一方法是?

我们这样做是因为我们想要降低服务器上的安全性,并从开发人员那里拿走db_owner,这已经成为多年来的常态。创建这种机制将满足他们关于无法访问的唯一剩余投诉。他们担心我们不会回答一个页面,他们将无法解决问题,所以这会照顾到这一点。

当然,任何有关安全漏洞的建议也会受到赞赏。

+0

来吧,使用QUOTENAME。你不想要任何'exec SQLELR_Login_CREATE ...,@DATABASE ='master; exec IAmInUrDatabsePwningUrTables;',...' – 2009-12-08 22:37:33

+0

如果所有参数都是通过.net与SqlParameter提交的,这仍然是一个漏洞?也许有人可以尝试从另一个SQL模块调用? – Sam 2009-12-08 23:47:45

+0

是的,它仍然是一个漏洞。作为一般规则,绝不要依赖客户端在服务器上安全(即SqlParameter),因为攻击者不会使用客户端。特别是,任何低权限的用户都可以使用此过程来挂载特权升级攻击,通过Sql Injection向量利用EXECUTE AS特权。换句话说,任何客人都可以成为系统管理员。 – 2009-12-09 00:29:08

回答

1

工作过程中的EXECUTE AS子句将您置于'作为执行者'笼中,请参阅Extending Database Impersonation by Using EXECUTE AS。因为该过程的EXECUTE AS是数据库主体,所以作为上下文执行将仅在数据库内受信任。

有两种解决方法,ALTER DATABASE [SQLEmergencyLoginRequest] SET TRUSTWORTHY ON的500lb大锤或代码签名的手术精准工具,例如Call a procedure in another database from an activated procedure。我强烈建议代码签名的方法:

  • 了解创建于SQLEmergencyLoginRequest证书
  • 标志的程序
  • 下降证书的私钥,以防止将来用于签名
  • 导出证书
  • 将主证书导入
  • 创建从证书派生的登录名
  • grant AUTHENTICATE on服务器将证书导出登录
  • 补助所需程序,此派生登录

这所有其他权限的将确保程序拥有所需的全部权限的做它的工作,在任何数据库。每次更改签名过程时都必须重做整个签名过程。

+0

“将该过程所需的所有其他特权授予此派生登录”我对为什么将用户放入主服务器以及需要授予哪些权限有点困惑,因此它可以在每个数据库中创建登录名和用户。再次感谢您的帮助Remus。 – Sam 2010-02-03 19:14:22

+0

CREATE LOGIN需要在服务器级别进行ALTER ANY LOGIN。 CREATE USER需要数据库中的ALTER ANY USER。您可以将ALTER ANTER LOGIN授予证书派生登录名,但要在数据库中创建用户,还需要服务器级权限(因为您无法在每个数据库中真实地复制证书),并且此权限为CONTROL SERVER。虽然它是一个非常强大的权限,但在代码签名下使用它是可以的。 – 2010-02-04 01:59:58

+0

似乎CONTROL SERVER在sysadmin服务器角色执行时不起作用。 – Sam 2010-02-08 14:48:21