第九篇 SQL Server安全透明数据加密

时间:2021-05-28 19:17:02

本篇文章是SQL Server安全系列的第九篇,详细内容请参考原文


Relational databases are used in an amazing variety of applications with connections from a dizzying array of clients over widely distributed networks,特别是互联网,使得数据几乎向任何人,任何地方开放。数据库可以包含相当大部分的人类知识,包括高度敏感的个人信息和关键数据。
数据库的这些特性使得有人想要窃取数据或通过篡改以损害它的主人。确保你的数据是安全的是一个关键部分来配置SQL Server和开发应用程序存储数据。这一系列将探索SQL Server 2012安全基础,那样你可以保护你的数据和服务器资源,getting as granular as you need to be to protect against the unique security threats that can affect your data.大部分的功能适用于早期版本的SQL Server,但我也会讨论只适用于SQL Server 2012和以后版本的功能。
即使是一个安全设计很好的数据库,如果攻击者能够访问包含数据库的磁盘文件,就容易受到攻击。单元级加密可以保护一些数据,但对这种攻击要完全保护,就有必要加密文件,而不只是数据。这正是透明数据加密(TDE),在这一篇你会知道TDE是什么,它是如何工作的,以及如何利用它来保护你的数据库文件。
透明数据加密(TDE)
在SQL Server 2008,微软推出透明数据加密。TDE是实时在文件级别加密和解密数据文件和日志文件。相比第八篇讲到的在列级上的数据加密,这种加密数据库中的所有数据。在第八篇你必须明确使用T-SQL函数加密数据,使用对称密钥,非对称密钥或证书来保护和解密数据。
TDE在文件级加密数据库。加密是透明的,它不会影响你访问数据。不需要任何特殊的编程,有专门为管理TDE支持的T-SQL。这使得TDE很容易设置和维护,虽然它需要更多的工作,在复制和移动数据库到SQL Server实例的不同位置。
一旦你为数据库启用了TDE,当数据写入到数据库时TDE会自动加密,当读取时会自动解密。TDE的目的是在数据和日志文件保护数据,保护它的安全防止攻击者试图直接从文件访问数据。如果你需要通过一个过夜的包裹递送服务来运送你的数据库文件,比如FedEx或者UPS,这样的场景就很有用了。没有TDE,攻击者可以从货车后面偷你的包裹,然后在一个拥有系统管理员权限的实例上附加,并获取数据。但如果在数据库中启用了TDE,整个数据集是安全加密的;在没有密钥的情况下,是没有办法访问数据的。其他一些TDE可用场景是你担心攻击者,比如内部人员,可能会以某种方式访问物理数据文件,或者你需要保护副本存档的数据库安全。
TDE是如何工作的
TDE需要一个证书来访问物理数据文件。没有用于加密数据库的证书,数据是不可用的。这意味着,不要把证书备份和它所保护的数据库保存在很近的地方!否则攻击者会得到所有她需要的来解密你的数据。她需要做的是在她控制的SQL Server实例上安装证书,并用它来附加数据库,然后就可以获取解密后的数据。
需要注意的是TDE加密所有写入到数据库的数据,然后根据查询解密需要的数据。所以,只有当数据是静止的、存储在数据库中,它才被TDE保护。TDE以每个8K的页加密和解密数据。
如果在一个SQL Server实例的任何数据库设置成TDE保护,SQL Server会自动用TDE保护tempdb库。这是有道理的,因为一些受保护数据库的数据可以暂时存储在tempdb。问题是,加密会导致性能下降。存储在tempdb中的所有数据都要加密,实例中的其他没有使用TDE保护的数据库存储到tempdb也需要加密。因此,这些数据库的性能可能会受到影响。
为了让一切运转,你需要有权限在master数据库创建database master key和证书,在用户数据库上有control权限启用TDE。大多数时候,系统管理员会启用数据库的TDE,所以权限需求应该不是问题。
TDE的局限性
为了有效地使用TDE,你应该明白TDE能做什么以及它不擅于做什么。考虑TDE的这些局限:
->你不能加密数据库中的数据的一个子集,它是全部或无
->TDE是无法通过数据库引擎限制数据的访问。通过TDE数据访问是不变的。如果你有一个用户正在运行一个应用程序,并且应用程序或用户有访问数据库中的数据所需的权限,TDE不会以任何方式改变数据访问。它只是保护数据库文件。
->TDE不是服务器、SQL Server实例、或存储在数据库中的敏感数据安全的替代品。你还需要仔细考虑使用防御纵深的分层安全保护你的数据。TDE is just one of those layers designed to protect against specific attacks against data at rest in the data and log files.
->TDE最大的缺点之一是,文件流数据是不加密的。This is data blobs stored outside of SQL Server but managed and secured by the database.
->TDE只在SQL Server企业版和开发版中能使用。
正如你可以看到,TDE有这些“限制”,这表明它并不能作为一种安全的灵丹妙药。但如果你的数据威胁刚好对应于它所提供的保护,TDE可以是一个重要的安全功能。
TDE性能
TDE一个你需要考虑的问题是性能。加密是一个昂贵的操作。TDE的表现相当不错,因为TDE不加密SQL缓存中的数据。只有当数据被写入磁盘,SQL Server才对它进行加密。因此,如果数据在缓存中,加密并不一定会发生,从而提高整体效率。微软已经花费了大量的时间在数据库中尽可能高效的加密,但在读或写数据的时候仍然会导致性能问题,因为加密使用复杂的算法。
使用TDE
示例代码显示如何使用TDE以及对数据库的影响。脚本中的部分代码,可能需要更改文件路径以适应你本地SQL Server的实例,比如数据库备份位置和证书备份位置。

-- Make a copy of AdventureWorks2012 database
-- Change the path to the appropriate backup directory
BACKUP DATABASE AdventureWorks2012
TO DISK = N'D:\SQL2012\MSSQL11.SQL12\MSSQL\Backup\AdventureWorks2012.bak'
WITH NOFORMAT, INIT, NAME = N'AdventureWorks2012 Full Database Backup',
SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10;
GO RESTORE DATABASE AdventureWorks2012Copy
FROM DISK = N'D:\SQL2012\MSSQL11.SQL12\MSSQL\Backup\AdventureWorks2012.bak'
WITH
FILE = 1, NOUNLOAD, REPLACE, STATS = 10,
MOVE 'AdventureWorks2012_Data' TO N'D:\SQL2012\MSSQL11.SQL12\MSSQL\DATA\AdventureWorks2012Copy.mdf',
MOVE 'AdventureWorks2012_Log' TO N'D:\SQL2012\MSSQL11.SQL12\MSSQL\DATA\AdventureWorks2012Copy.ldf';
GO

示例代码会执行下面四步来启用数据库上的TDE:
1、master库创建一个master key
2、master库创建一个用master key保护的证书
3、创建数据库加密密钥,用证书保护
4、启用数据库TDE
代码9.1首先用一个强密码创建database master key,然后创建AdventureWorks2012TDECert证书。作为预防,代码备份证书。你应该把它保存到一个安全的地方,以防迁移数据库时需要:

-- Create a certificate in master to use with TDE
USE master;
GO
-- TDE hooks into encryption key hierarchy in SQL Server
CREATE MASTER KEY ENCRYPTION BY PASSWORD = '!drJP9QXC&Vi%cs';
GO
-- Create the certificate used to protect the database encryption key
CREATE CERTIFICATE AdventureWorks2012TDECert WITH SUBJECT = 'Certificate to implement TDE on AdventureWorks2012Copy';
GO -- Backup the certificate
-- Either create the D:\SQL2012 folder or change it in the code below
BACKUP CERTIFICATE AdventureWorks2012TDECert TO FILE = 'D:\SQL2012\AdventureWorks2012TDECert'
WITH PRIVATE KEY ( FILE = 'D:\SQL2012\AdventureWorks2012TDECertPrivateKey' ,
ENCRYPTION BY PASSWORD = 'RISiS9Ul%CByEk6' );
GO
-- Must backup private key as well

代码9.1 创建证书并备份证书
在深入配置TDE之前先运行代码9.2。语句会列出当前实例下加密的数据库,以及加密状态。在一个全新、原始的实例上,应该不会返回任何结果集。在应用TDE之后,你会看到结果有所改变:

SELECT DB_NAME(database_id) AS DatabaseName,
key_algorithm AS [Algorithm],
key_length AS KeyLength,
CASE encryption_state
WHEN 0 THEN 'No database encryption key present, no encryption'
WHEN 1 THEN 'Unencrypted'
WHEN 2 THEN 'Encryption in progress'
WHEN 3 THEN 'Encrypted'
WHEN 4 THEN 'Key change in progress'
WHEN 5 THEN 'Decryption in progress'
END AS EncryptionStateDesc,
percent_complete AS PercentComplete
FROM sys.dm_database_encryption_keys;
GO

代码9.2 罗列SQL Server实例上加密的数据库
现在是时候启用AdventureWorks2012Copy的TDE。执行代码9.3,使用之前在master库创建的证书创建一个数据库加密密钥。如果你没有备份证书的话会收到一条警告。然后使用ALTER DATABASE带上SET ENCRYPTION ON子句启用TDE,根据数据库的大小和服务器的速度,它可能需要一段时间才能完全加密数据库,可能数小时或数天。

USE AdventureWorks2012Copy;
GO
-- Create the database encryption key for TDE. Analogous to database master key for data encryption.
CREATE DATABASE ENCRYPTION KEY
WITH ALGORITHM = TRIPLE_DES_3KEY
ENCRYPTION BY SERVER CERTIFICATE AdventureWorks2012TDECert;
GO
-- Get a warning about backing up the key, if you haven't already
-- ...take the advice and back it up! -- Now need to turn TDE on.
ALTER DATABASE AdventureWorks2012Copy SET ENCRYPTION ON;
GO

代码9.3 创建数据库加密密钥并启用TDE
当它在加密数据库的时候,重新执行代码9.2。你会看到类似图9.1的结果。注意图中显示两个数据库:AdventureWorks2012Copy数据库启用了TDE,tempdb库是自动应用加密。一旦初始化加密完成,PercentComplete列会显示为0(是的,列名有点误导人,它完成时并不是真实的完成百分比)。
第九篇 SQL Server安全透明数据加密
图9.1 sys.dm_database_encryption_keys监视加密进度
注意图中AdventureWorks2012Copy是由TRIPLE_DES_3KEY算法加密的。这是因为在代码9.3中我们指定的加密算法。你可以选择SQL Server中支持的任何加密算法。同时注意tempdb库使用默认的AES加密算法。
使用代码9.4测试加密。只要在开启TDE之前有访问数据的必要权限,你就依然能够访问数据。应用程序访问数据也是一样。

SELECT TOP 500 * FROM Production.Product;

代码9.4 测试开启TDE后访问数据
如果你想关闭数据库的TDE,可以使用代码9.5

ALTER DATABASE AdventureWorks2012Copy
SET ENCRYPTION OFF;

代码9.5 禁用数据库的TDE功能
测试TDE
测试安全特性以确保其按照你期望的方式工作通常是明智的。示例代码包含部分测试TDE步骤,包括假设你意外地删除TDE中用于保护数据库加密密钥的证书。代码9.6先备份AdventureWorks2012Copy数据库,接着删除AdventureWorks2012Copy数据库,然后删除AdventureWorks2012TDECert证书,从而模拟证书丢失。(这也模拟了当你试图附加加密数据库到不同的、且没有安装原始证书的SQL Server实例)

BACKUP DATABASE AdventureWorks2012Copy
TO DISK = N'D:\SQL2012\MSSQL11.SQL12\MSSQL\Backup\AdventureWorks2012Copy.bak'
WITH NOFORMAT, INIT, NAME = N'AdventureWorks2012Copy Full Database Backup',
SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 10;
GO
USE master
GO
DROP DATABASE AdventureWorks2012Copy;
GO
-- Oops! We lost the certificate and don't have a copy!
-- Or, going to restore the database to another server instance
DROP CERTIFICATE AdventureWorks2012TDECert;
GO

代码9.6 备份数据库、删除数据库、删除证书
接下来,尝试用代码9.7还原数据库。你会看到如图9.2所示的错误信息。这是TDE的保护机制:无法还原或附加数据库到一个没有安装原始加密证书的SQL Server实例上。

RESTORE DATABASE AdventureWorks2012Copy
FROM DISK = N'D:\SQL2012\MSSQL11.SQL12\MSSQL\Backup\AdventureWorks2012Copy.bak'
WITH
FILE = 1, NOUNLOAD, REPLACE, STATS = 10;

代码9.7 尝试还原数据库
第九篇 SQL Server安全透明数据加密
图9.2 在没有安装原始加密证书的实例还原TDE数据库的出错信息
但是如果你备份了证书,那么可以用代码9.8来从备份文件中还原证书,使用之前在备份证书时保护证书的密码,然后尝试还原数据库。这次数据库成功被还原了。

-- Restore the certificate
CREATE CERTIFICATE AdventureWorks2012TDECert
FROM FILE = 'D:\SQL2012\AdventureWorks2012TDECert'
WITH PRIVATE KEY ( FILE = 'D:\SQL2012\AdventureWorks2012TDECertPrivateKey',
DECRYPTION BY PASSWORD = 'RISiS9Ul%CByEk6');
-- Now try to restore the database
RESTORE DATABASE AdventureWorks2012Copy
FROM DISK = N'D:\SQL2012\MSSQL11.SQL12\MSSQL\Backup\AdventureWorks2012Copy.bak'
WITH
FILE = 1, NOUNLOAD, REPLACE, STATS = 10;

代码9.8 从备份文件中还原证书,然后还原数据库
TDE与列级数据加密对比
在第八篇和第九篇,你应该对SQL Server提供的这两种加密形式有一个很好的理解。为总结主要不同点,在列级的数据加密:
->加密有更细的粒度,你可以在一个单独的表中加密单独的一列
->只有在使用的时候才解密数据,如果数据很少被使用,它就很少会被解密
->你需要更改表结构以适应加密的二进制数据,并将应用程序更改为包含加密和解密代码
->你不能很容易地搜索和排序加密数据,索引基本上是没有用的。有一些解决方法,但它们不是有效的,攻击者可以利用探索特性来获得一个立足点
在一般情况下,你会使用列级数据加密少量的数据以保护最敏感的数据,并节约服务器上处理周期。
这就引出了一个问题:SQL Server 2008及之后版本应该使用哪种形式的加密?关键是要了解你需要防护的威胁,这在执行任何安全功能时是至关重要的。
如果威胁是对数据和日志文件的盗用和滥用,使用透明数据加密。TDE会阻止别人附加数据库文件到另一个SQL Server实例获取数据。
但是如果威胁是在你的服务器上的数据,列级加密可能是更好的选择。正确地使用列级数据加密可以防止攻击者访问数据库服务器时去访问数据。
如果你不能在两者之间决定,那就有可能需要使用两种类型的加密来保护数据。幸运地是,它们一起工作很和谐,每一个保护自己独特的威胁。

-- *** Clean up ***
-- ****************
USE master;
GO
IF DB_ID('AdventureWorks2012Copy') IS NOT NULL DROP DATABASE AdventureWorks2012Copy;
GO
-- Can't turn off TDE in tempdb once it is on
DROP CERTIFICATE AdventureWorks2012TDECert;
GO
DROP MASTER KEY;
GO

总结
透明数据加密在文件级别实时加密和解密数据和日志文件。这种加密数据库中的所有记录数据,防止攻击者将数据库附加到另一个SQL Server实例获取数据。如果你需要抵御数据文件的盗窃和滥用,TDE提供强有力的数据保护,并且架构或编程不需要改变。Used properly, it can provide a strong layer of security for overall defense in depth.