开发者

Avoiding the use of SET TRUSTWORTHY ON

I'm working with a system which had to create objects in one database based on objects being created in another database. The objects are not duplicates, so I can't simply replicate the objects.

I have code below which gives a simplified demonstration of what I'm trying to do. If you uncomment the ALTER DATABASE statements then it will run without any errors. That has the potential of creating a security hole though, so I'd like开发者_如何转开发 to avoid it if possible.

I've tried using certificates and impersonation, but nothing seems to work. I think that the DDL trigger is ignoring a lot of the security when it comes to users vs. logins. I've also tried creating a stored procedure in Test_DB_2 which calls the SP in Test_DB_1 and having the trigger call that stored procedure instead, but that didn't help either.

So, your challenge, if you're willing to accept it, is to get the code below to work without setting TRUSTWORTHY ON (or turning on db chaining if that has any effect).

Thanks for any help that you can give!

/************************
   SET-UP THE TEST
************************/
USE master
GO
CREATE LOGIN Test_Security_Login WITH PASSWORD = 'p@ssw0rd1!'
CREATE DATABASE Test_DB_1
CREATE DATABASE Test_DB_2
GO
USE Test_DB_1
GO
CREATE PROCEDURE dbo.Create_View
AS
BEGIN
 EXEC('CREATE VIEW Test_View AS SELECT 1 AS one')
END
GO
CREATE USER Test_Security_User FOR LOGIN Test_Security_Login
GRANT EXECUTE ON dbo.Create_View TO Test_Security_User
GO
USE Test_DB_2
GO
CREATE TRIGGER DDL_TRIGGER ON DATABASE WITH EXECUTE AS 'dbo' FOR DDL_VIEW_EVENTS
AS
BEGIN
 EXEC Test_DB_1.dbo.Create_View
END
GO
CREATE USER Test_Security_User FOR LOGIN Test_Security_Login
EXEC sp_addrolemember 'db_ddladmin', 'Test_Security_User'

/************************
   RUN THE TEST
************************/
USE Test_DB_2
GO
--ALTER DATABASE Test_DB_1 SET TRUSTWORTHY ON
--ALTER DATABASE Test_DB_2 SET TRUSTWORTHY ON
EXECUTE AS USER = 'Test_Security_User'
GO
CREATE VIEW dbo.Test_View_2 AS SELECT 2 AS two
GO
REVERT
GO

/************************
   CLEAN-UP
************************/
USE master
GO
DROP DATABASE Test_DB_1
DROP DATABASE Test_DB_2
DROP LOGIN Test_Security_Login
GO


Too easy. Use Code Signing:

  • create self signed certificate in db1
  • sign the trigger with a certificate
  • drop private key to prevent abuse
  • export certificate into db2 (backup/create from file)
  • create credential from certificate in db2
  • grant AUTHENTICATE and any other necessary permission to certificate derived credential
  • ?
  • profit

This is bullet proof. See Call a procedure in another database from an activated procedure for a fully fledged example.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜