服务器级安全可能是系统管理员最关心的问题,而对于数据库来说,所有操作都是在生产环境中完成的。在大多数情况下,数据库管理员会将数据库细节的问题留给数据库开发人员处理,只要开发人员在环境的限制内工作。SQL Server 2008提供了大量确保数据库安全的功能。
数据加密
SQL Server 2000 及其早期版本不支持加密存储在数据库中的数据。为什么需要加密存储在安全性良好的数据库(位于安全地嵌套在最新的防火墙之后的安全服务器上)中的数据?这是因为一个重要的、叫做 defense in depth 的旧安全规范。Defense in depth 的意味着分层防御,即使攻击者成功打破了最外层防御,他们仍然需要突破一层接一层的防御才能获得成功。在数据库中,这意味着攻击者通过了防火墙和从服务器到数据库的 Windows 安全以后,仍然需要进行一些恶劣的、野蛮的和强制的黑客攻击来解码您的数据。另外,在如今这个立法保护数据和隐私的大环境中,数据需要加强保护。
SQL Server 2008 使用对称密钥、非对称密钥和数字证书,为各种类型的数据加密提供了丰富的支持。最出色的是,它为您管理密钥,而密钥管理是迄今为止加密中最难的部分。保密是一件很难的事情。
管理员可能至少需要管理图10所示层次结构中的上级密钥。数据库管理员需要理解服务器级的服务主密钥和数据库级的数据库主密钥。每一个密钥都保护其子密钥,子密钥又保护其子密钥,从树形结构图依次向下。密码保护对称密钥或证书时例外,这是 SQL Server 使用户管理自己的密钥,以及负责保密密钥的方法。
图 1:SQL Server 2008 中的加密密钥层次结构
注意:Microsoft 不推荐直接使用证书或非对称密钥加密数据。非对称密钥加密的速度很慢,并且使用此机制保护的数据量有限(这取决于密钥模数的大小)。可以使用密码,而不是数据库主密钥保护证书和非对称密钥。
服务主密钥是一个规定 SQL Server 中所有密钥和证书的密钥。它是 SQL Server 在安装期间自动创建的对称密钥。显然,它是一个至关重要的密钥,因为如果此密钥泄露了,那么攻击者最终将解码服务中由 SQL Server 管理的每个密钥。Windows 中的数据保护 API (Data Protection API, DPAPI) 保护服务主密钥。
SQL Server 为您管理服务主密钥。虽然您可以对其执行维护任务,将其转存到一个文件中,重新生成它,以及从文件中将其还原。不过,大多数情况下,无需对密钥做任何更改。备份服务主密钥以防止密钥损坏对于管理员来说是明智的选择。
在数据库范围内,数据库主密钥是数据库中所有密钥、证书和数据的根加密对象。每个数据库都有惟一的主密钥;尝试创建第二个密钥时,会出现错误提示。必须在使用前通过 CREATE MASTER KEY Transact-SQL 语句和用户提供的密码创建一个数据库主密钥:
CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'EOhnDGS6!7JKv'
SQL Server 使用由密码和服务主密钥派生出来的三重 DES 密钥加密密钥。第一个副本存储在数据库中,第二个存储在主数据库中。由于服务主密钥保护数据库主密钥,因此可能在需要时由SQL Server 自动加密数据库主密钥。最终应用程序或用户无需使用密码显式打开主密钥,这是层次结构保护密钥的主要优势。
分离一个存在现有主密钥的数据库,并将其移动到另一个服务器上是一个难题。问题在于新服务器的服务主密钥与旧服务器的服务主密钥不同。因此,服务器不能自动解密数据库主密钥。可以通过使用加密密码打开数据库主密钥,然后使用 ALTER MASTER KEY 语句以新的服务主密钥对其加密的方法避开这个问题。否则,总是需要显式打开数据库主密钥以后才能使用。
如果存在数据库主密钥,那么开发人员就可以使用它创建三种类型中的任何一种密钥,具体取决于加密所需求的类型:
非对称密钥,使用公钥/私钥对进行公钥加密
对称密钥,用于在同一个密钥分别加密和解密数据的方面共享秘密
证书,实质上用于包装公钥
由于所有加密选项及其已经深层集成于服务器和数据库中,因此现在加密是将防御的最终层添加到数据的可行方法。然而,需明智使用工具,因为加密给服务器增加了大量的处理开销。
透明数据加密
在 SQL Server 2005 中,可以使用数据库引擎加密功能,通过编写自定义 Transact-SQL 加密数据库中的数据。SQL Server 2008 引入了透明的数据加密,改进了这种状况。
透明数据加密在数据库级执行所有加密操作,这消除了应用程序开发人员创建自定义代码来加密和解密数据的需要。数据在写入磁盘时被加密,在从磁盘读取时解密。通过使用 SQL Server 透明地管理加密和解密,就可以在不改变现有应用程序的情况下确保数据库中业务数据的安全,如图 11 所示。
图 2:透明数据加密
数据库加密密钥(Database Encryption Key,DEK)用于执行加密和解密操作,该DEK存储在数据库启动记录中,以便在恢复过程中使用。可以使用服务主密钥(Service Master Key)或硬件安全模块(Hardware Security Module,HSM)保护 DEK。HSM 通常是 USB 设备或智能卡,因为不易被盗或丢失。
扩展的密钥管理
随着法规遵从性需求的不断增长以及对数据隐私的整体关注,越来越多的组织将加密用作提供深层防御解决方案的手段。随着组织越来越多地使用加密和密钥来保护数据,密钥管理也变得更加复杂。一些高安全性数据库要使用数千个密钥,并且必须部署一个系统来存储、注销和重新生成这些密钥。而且,应该将这些密钥与数据分开存储以增强安全性。
SQL Server 2008 为第三方供应商的使用公开了加密功能。这些解决方案可以与 SQL Server 2005 和 SQL Server 2008 数据库无缝地一起工作并提供了企业级专用密钥管理。这将密钥管理工作负载从 SQL Server 转移到了专用密钥管理系统。
SQL Server 2008 中扩展的密钥管理还支持使用 HSM 提供密钥与数据的物理分离。
代码模块签名
在 SQL Server 中提供加密的一个好处就是它提供了使用证书对代码模块(存储过程、函数、触发器和事件通知)进行数字签名的能力。这提供了对数据库表和其他对象访问的更细粒度的控制。像加密数据一样,您使用证书中的私钥签名代码。其结果是在该经过签名的代码模块中使用的表只能通过该代码访问并且不允许在代码模块之外。换句话说,只能使用已经用于签名该模块的证书获得对该表的访问。
对于存储过程而言,效果也是一样的。例如,如果有完整的所有权链,您可以谨慎控制哪些用户获得该过程的 EXECUTE 权限,并且可以拒绝他们对基础表的直接访问。但这在过程的所有权链被破坏或执行动态 SQL 时不起作用,此时要求执行该过程的用户拥有对基础表的权限。实现同样效果的另一种方式是使用 EXECUTE AS,但这改变了过程执行的安全上下文。这可能不是理想的情况,例如,需要在表中记录实际使该过程运行的用户时(没有要求将用户名作为过程的参数)。
签名代码模块的另一个好处就是防止对代码模块作出未经授权的更改。像其他经过数字签名的文档一样,在代码改变时,证书将失效。代码不在证书上下文中执行,因此任何被提供了证书访问权限的对象都将不可访问。
要继续访问它们,需要创建一个证书,将该证书与新用户关联并使用该证书签名过程。授予该用户执行该存储过程必要的任何权限。实质上,已经将该用户作为次级身份标识添加到了存储过程安全上下文中。然后,授予需要执行该过程的任何用户或角色执行权限。以下代码展示了这些步骤。假设您想要签名 mySchema.GetSecretStuff 过程,并且所有引用的对象已经存在于数据库中:
CREATE CERTIFICATE certCodeSigning
ENCRYPTION BY PASSWORD = 'cJI%V4!axnJXfLC'
WITH SUBJECT = 'Code signing certificate'
GO
-- Sign the stored procedure
ADD SIGNATURE TO mySchema.GetSecretStuff BY CERTIFICATE certCodeSigning
WITH PASSWORD = 'cJI%V4!axnJXfLC'
GO
-- Map a user to the certificate
CREATE USER certUser FOR CERTIFICATE certCodeSigning
GO
--Assign SELECT permissions to new certUser
GRANT SELECT ON SocialSecurity TO certUser
GO
-- Grant execute permission to the user who will run the code
GRANT EXECUTE ON mySchema.GetSecretStuff TO ProcedureUser
GO
现在只有明确授予对该存储过程具有 EXECUTE 权限的用户能够访问该表的数据。