设为首页 收藏本站
查看: 842|回复: 0

[经验分享] OPEN SYMMETRIC KEY scope in SQL Server

[复制链接]

尚未签到

发表于 2015-6-30 12:10:29 | 显示全部楼层 |阅读模式
  
最近我收到一些关于对称密钥有效范围的问题,特别是在模块内(存储过程)打开对称密钥。其中一个问题是,如果在存储过程内执行打开密钥(OPEN SYMMETRIC KEY)的操
作,而退出存储过程前没有将密钥关闭,会导致密钥“泄露”到模块以外。

BOLOPEN SYMMETRIC KEY(在备注下方)文章中,我们已经写明,打开的密钥在整个会话范文内有效,而仅仅是在执行上下文内(包括存储过程),并且密钥在被显示关闭(使用CLOSE SYMMETRIC KEY语句)或者会话终止前密钥都是处于打开状态的。

如何保证密钥在模块内打开并且不会被“泄露”出去呢?需要显示密钥关闭。目前为止SQLSERVER 2005还不能将OPEN SYMMETRIC KEY的有效范围限制在模块内。

示例:


CREATE CERTIFICATE [cert_keyring_demo]
  WITH SUBJECT = 'key ring demo'

go


CREATE SYMMETRIC KEY [symkey_keyring_demo]
  WITH ALGORITHM = AES_192
  ENCRYPTION BY CERTIFICATE [cert_keyring_demo]

go


CREATE USER [lowpriv_user] WITHOUT LOGIN
go

CREATE PROC [sp_openkey]
-- We will be runnign this module under an impersonated context
WITH EXECUTE AS OWNER
AS
  OPEN SYMMETRIC KEY [symkey_keyring_demo]
    DECRYPTION BY CERTIFICATE [cert_keyring_demo]

  -- Notice that the key is not being closed on purpose

  --

go


-- Grant minimum privielges
--
GRANT EXECUTE ON [dbo].[sp_openkey] TO [lowpriv_user]
GRANT VIEW DEFINITION ON SYMMETRIC KEY::[symkey_keyring_demo] TO [lowpriv_user]

go

EXECUTE AS USER = 'lowpriv_user'
go


SELECT * FROM sys.openkeys

go

-- fails with error 15151
--
OPEN SYMMETRIC KEY [symkey_keyring_demo]
     DECRYPTION BY CERTIFICATE [cert_keyring_demo]
go


-- This will succeed
--
EXEC [dbo].[sp_openkey]
go



-- And we can verify that the key is opened on our session.
SELECT * FROM sys.openkeys
go



-- and we can encrypt & decrypt
declare @blob varbinary(1000)
declare @pt varchar(1000)
SET @blob = encryptbykey( key_guid( 'symkey_keyring_demo'), 'data' )
SET @pt = convert( varchar(1000), decryptbykey( @blob ))
SELECT @pt, @blob
go


-- We can swithc context DSC0000.gif
REVERT

go

-- and verify that the key ring is still opened
SELECT * FROM sys.openkeys

go

-- And the key remains opened until we close it
-- or we terminate the session
--
CLOSE SYMMETRIC KEY symkey_keyring_demo

go



上面的代码故意使密钥在模块结束后还保持打开状态,但是这种情况也可能是由错误的操作引起,导致了密钥的泄露(也就是说 应用程序中存在这样的bug

例如:


CREATE TABLE [dbo].[tabl_keyring_demo]( id int IDENTITY PRIMARY KEY,
  data varbinary(1000), LastUsedDate datetime )
go


OPEN SYMMETRIC KEY [symkey_keyring_demo]
DECRYPTION BY CERTIFICATE [cert_keyring_demo]
go



INSERT INTO [dbo].[tabl_keyring_demo]
  VALUES ( encryptbykey( key_guid( 'symkey_keyring_demo'), 'lowpriv_user' ), GetDate())
INSERT INTO [dbo].[tabl_keyring_demo]
  VALUES ( encryptbykey( key_guid( 'symkey_keyring_demo'), 'outdated_user' ), GetDate())
go

CLOSE SYMMETRIC KEY [symkey_keyring_demo]
go



CREATE PROC [sp_keyring_demo2]( @id int )
WITH EXECUTE AS OWNER
AS
-- 改存储过程目的为解密数据,
-- 并在退出存储过程前关闭密钥
--
declare @username varchar(1000)
if( EXISTS(SELECT count(*) FROM [dbo].[tabl_keyring_demo] WHERE Id = @id))
BEGIN
     OPEN SYMMETRIC KEY [symkey_keyring_demo]
          DECRYPTION BY CERTIFICATE [cert_keyring_demo];
         
     SELECT @username = convert( varchar(1000), decryptbykey( data ))
       FROM [dbo].[tabl_keyring_demo] WHERE Id = @id;

     -- For demonstration purposes, I will add a DDL statetemnt that I know
     -- will fail the second time I execute the module
    if( @username is not null )
    BEGIN
          EXECUTE AS USER = @username
          -- do something interesting under this context
          REVERT
    END

     -- Updating LastUsedDate column
     UPDATE [dbo].[tabl_keyring_demo] SET LastUsedDate = GetDate() WHERE Id = @id;
     CLOSE SYMMETRIC KEY [symkey_keyring_demo];

END

go
GRANT EXECUTE ON [dbo].[sp_keyring_demo2] TO [lowpriv_user]
go



--Let's give it a try
EXECUTE AS USER = 'lowpriv_user'
go

-- This one will work as expected
--
EXEC [dbo].[sp_keyring_demo2] 1
go
-- and no keys in the key ring
--
SELECT * FROM sys.openkeys
go



-- 这次运行时会失败,出现15517错误
-- 该错误会终止batch
-- 导致密钥无法关闭
--

EXEC [dbo].[sp_keyring_demo2] 2
go

SELECT * FROM sys.openkeys
go

--Clean up
CLOSE SYMMETRIC KEY [symkey_keyring_demo];
go

REVERT

go



注意,上面的代码设不当,使密钥打开的时间过长,代码的错误处理也可能失败。下面是改进代码:


ALTER PROC [sp_keyring_demo2]( @id int )
WITH EXECUTE AS OWNER
AS

-- The intention of this SP is to decrypt data, but close the key
-- before leaving the module frame
--

declare @username varchar(1000)
if( EXISTS(SELECT count(*) FROM [dbo].[tabl_keyring_demo] WHERE Id = @id))
BEGIN
     SELECT @username = convert( varchar(1000), DecryptByKeyAutoCert( cert_id('cert_keyring_demo'), null, data ))
       FROM [dbo].[tabl_keyring_demo] WHERE Id = @id;

     -- For demonstration purposes, I will add a DDL statetemnt that I know
     -- will fail the second time I execute the module

    if( @username is not null )
    BEGIN
          BEGIN TRY
              EXECUTE AS USER = @username
              -- do something interesting under this context
              REVERT
          END TRY

          BEGIN CATCH
              print 'Unexpected error'
              print error_message()
              -- add code to handle error properly here
              --
              RAISERROR( 'Error in impersonated context', 16, 1 )
          END CATCH

    END

     -- Updating LastUsedDate column
     UPDATE [dbo].[tabl_keyring_demo] SET LastUsedDate = GetDate() WHERE Id = @id;
END

go

-- succeeds
--
EXEC [dbo].[sp_keyring_demo2] 1
go



-- fails gracefully
--
EXEC [dbo].[sp_keyring_demo2] 2
go



    如你所见,密钥是在会话范围内有效的。如果你要编码一种模块:密钥只能被模块的调用者使用,并只在模块内有效。 密钥的这种特性会影响到模块的设计。 所以如果你的应用程序用到了OPEN SYMMETRIC KEY语句,你要考虑到密钥的这种限制和SQLSERVER错误处理的方式。

一些提示,如何在保护调用者利益的情况下开打密钥:

·         如果可能,尽量用DecryptByKeyAuto语句代替DecryptByKey语句,使用DecryptByKeyAuto不需要显示地将密钥打开,该语句会自动打开密钥(并在解密后关闭密钥,译者注)
·         尽可能减少打开密钥和关闭密钥之间的代码,减少打开密钥却没有关闭密钥的逻辑错误
·         确保在代码内进行错误处理,使用TRY/CATCH防止模块过早终止


原文地址:OPEN SYMMETRIC KEY scope in SQL Server


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-81917-1-1.html 上篇帖子: 如何将 Excel 数据导入 SQL Server 下篇帖子: Sql Server 常用系统存储过程大全
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表