在保密你的服务器和数据,防备当前复杂的攻击,SQL Server有你需要的一切。但在你能有效使用这些安全功能前,你需要理解你面对的威胁和一些基本的安全概念。这篇文章提供了基础,因此你可以对SQL Server里的安全功能充分利用,不用在面对特定威胁,不能保护你数据的功能上浪费时间。
从让人眼花缭乱的客户端使用连接,通过到处分布的网络,尤其是互联网,关系数据库在各种应用程序里广泛使用。这使数据对任何人,在任何地方都可访问。数据库可以保存人类知识的很大部分,包括高度敏感的个人信息和让国际商务工作的关键数据。
对于想要偷取数据或通过篡改数据来伤害数据的拥有者的 人来说,这些功能使数据库成为有吸引力的目标。确保你的数据安全是SQL Server配置和使用它来保存数据的程序的重要部分。这个系列会探寻SQL Server 2012安全的基本,这样的话你可以保护你的数据和服务器资源,按你需要的安全等级来保护数据,免受这些威胁对你数据的影响。大部分信息对SQL Server的早期版本也适用,回到SQL Server 2005也可以,因为那是微软在产品里彻底检查安全的时候。但我也会谈论只在SQL Server 2012和后续版本里才有的功能。
一个重要的安全概念是深度防御,这就是说最好的安全分层保护而不是单靠一层保护。在你的网络,服务器,SQL Server实例,数据库都做了安全防护后,你可以添加最后一个通过加密敏感数据的强大数据保护层。这篇文章会探寻通过加密的数据库保护,同时包括数据在网络传输或内存里,和在表里休息。你会学到加密密匙的层级和你可以用来加密数据的各种密匙,还有你如何管理密匙,让服务器为你服务。
数据加密
到目前为止,你学习了SQL Server内建的很多强大安全功能,你可以用来保护你的数据和其它数据库对象。当你把这些和强大的网络完全结合,例如防火墙,最小特权用户账号和其它工具,你的数据应该非常安全,是不是?
答案还是不安全。虽然SQL Server 2012和SQL Server 2014目前已经是最安全的了(现在已经有SQL Server 2016了)——假设你充分并有效使用了安全功能——成功的攻击还是可能的。黑客是聪明的,因此很有可能会有某些人,在某个时间,找出黑入你数据库服务器的方法,并访问你的数据。即使你有100%的自信,这样的攻击还是可能的,你会在内部攻击的接收端发现自己——信任的员工做坏事了。
可以帮你理解为你的数据和你需要保护的其它资源,如何获得安全的最高级别的安全主体是深度防御。深度防御意味着你从未依赖于单个手段来保护任何有价值的。你加入层层不同的安全,这样的话,任何攻击者在拿到你的数据前,需要突破多个困难障碍。
这也是很多中世纪的城堡有个护城河作为第一道防线,里面有很多讨厌的动物在游泳。接下来一层是戒备森严,厚的的橡木门和几米厚的石墙。经常有另一个厚的,戒备森严的墙在外墙里。层层安全保护着里面的人和宝藏。
同样的方法,SQL Server有很多层安全,它有很多来建造和维护它们。但当你的数据是极其宝贵时,你可以加最后一层防护:加密。
SQL Server 2015是第一个丰富支持数据加密的版本,自那后的每个版本都做了一些改进。你可以使用各种加密类型,包括各种加密密匙,可以秘密传输数据为看不懂的胡言乱语,除非用户有密匙来解密。SQL Server支持各类加密算法。而且最重要的是,你可以让服务器来做管理密匙和的保持它们绝密的所有工作,这是加密最困难的部分。
提示:
加密是极其密集处理的操作,因为它需要复杂的计算。现代的计算机设备都很快,对于包含75个加密列,有1亿条数据的表,完成计算需要多个处理能力,对于设计不好的查询,你会有巨大的负担,会把动力不足的服务器累趴。使用加密来保护只值得终层保护的数据。
加密密匙(Encryption keys)
SQL Server允许使用三种加密密匙的任何之一。加密密匙是小块数据,当插入到算法后,转化数据为密文,这个密文如果没有正确的加密密匙,通常不能转为明文。
- 非对称密匙(Asymmetric Key):这种加密类型使用匹配的公共/私有密匙。一个密匙来加密数据,另一个解密它。你可以和任何人共享公共密匙,这样他们就加密任何数据,只有你才可以使用私密密匙来解密。SQL Server使用长度512、1024 或 2048 位私密密匙的RSA加密算法。关于这个算法,可以参考下维基百科。
- 对称密匙(Symmetric Key):在这个加密类型里,加密和解密数据的密匙数据是一样的。这有时被称为公有密匙,因为双方共享数据必须有相同的密匙。在某些情况下,很难使用对称密匙,因为安全传输秘密从一个地方到另一个地方是个问题。对称密匙在数据库里使用是个好主意,因为他们从未离开数据库。SQLServer支持RC4,RC2算法,也支持DES,AES算法家族。你可以在这个网站了解这些算法的概要信息。
提示:
微软在SQL Server 2012里已经明智的取消了RC4对称密匙,只有数据库的兼容级别为90或100(SQL Server 2005和SQL Server2008)才可以,这是为了保持向后兼容。RC4有很多弱点,最重要的是算法不散列话密匙——在加密前加些随机的文本到明文——这样在同样的密文里加密值是重复的。这让解密比应该有的难度更简单。即使你维护SQL Server的老版本,也不要使用RC4!
- 证书(Certificate):证书是对公共密匙的数字封装,作为非对称密匙加密的一部分。SQL Server可以为你创建使用的证书,或者你可以使用第三方证书授权。SQL Server使用互联网工程任务组(Internet Engineering Task Force)的X.509规格。
SQL Server使用如下的加密密匙层级,如插图8.1所示,来加密和保护你存储在数据库里的密匙。
插图8.1:加密密匙层级
在服务器级别,SQL Server的每个实例有个服务主密匙(Service Master Key),你用来加密低一层的其它密匙。这个密匙在SQL Server实例安装时创建。你可以备份和还原它,如果它已经泄露的话,也可以重新生成它,但绝大部分时间你可以不理会它。SQL Server会为你管理它,你也从不会直接使用它。服务主密匙在系统底层存储并保护,使用Windows数据保护API或DPAPI。
服务主密匙有一些内部使用,但我们这里的目的是SQL Server用它来加密和保护你创建的任何数据库主密匙(Database Master Keys)。在你加密的任何数据库里都需要数据库主密匙。它是加密和保护任何你创建密匙的对称密匙。你需要在数据库上下文里使用代码8.1的语句创建它。
1 USE EncryptionDB; 2 GO 3 4 CREATE MASTER KEY ENCRYPTION BY PASSWORD = 'gK#3hbQKDFQY0oF';
代码8.1:在EncryptionDB数据库里创建一个数据库主密匙的代码
提示:
如果你没有按这个系列文章逐篇阅读的话,你可以执行下列代码来初始化测试环境。
1 -- *** Beginning of setup code *** 2 -- ******************************* 3 4 -- Set up sample encryption database 5 USE master; 6 GO 7 8 -- Set up a login 9 IF SUSER_SID('User1') IS NOT NULL DROP LOGIN User1; 10 CREATE LOGIN User1 WITH password = '3f@$fWDY3QvP&K0'; 11 GO 12 13 IF DB_ID('EncryptionDB') IS NOT NULL DROP DATABASE EncryptionDB; 14 CREATE DATABASE EncryptionDB; 15 GO 16 USE EncryptionDB; 17 GO 18 19 CREATE USER User1 FOR LOGIN User1; 20 21 CREATE TABLE Customer ( 22 CustId int, 23 Name nvarchar(30), 24 City varchar(20), 25 CreditCardType varbinary(1000), 26 CreditCardNumber varbinary(1000), 27 Notes varbinary(4000)); 28 GO 29 30 -- Grant access on the table to user 31 GRANT SELECT, INSERT ON Customer to User1; 32 33 -- *** End of setup code *** 34 -- *************************
数据库主密匙保存2次:服务主密匙加密一次并保存,用你提供的密码再次加密。你可以移除其中一个,但不能同时移除。通常我们都2个都保留。
作为对称密匙,数据库主密匙在你使用它之前必须打开。打开密匙把它载入内存并解密它,这样就可以使用了。因为服务器的服务主密匙加密数据库主密匙,SQL Server可以Wie你自动打开密匙,这样的话你基本不需要直接打开它。想服务主密匙,你可以备份和还原它,想要的话也可以修改它。
你会使用插图8.1里的其它密匙来加密数据。箭头表示你用来加密和保护其它密匙的密匙。例如,你可以使用数据主密匙来加密其它证书或对称密匙。证书和非对称密匙只能保护对称密匙,对称密匙可以被证书,非对称密匙和其它对称密匙保护。
密匙管理
插图8.1战士了加密密匙的其它方面:你可以使用任何另一个密匙或密码来创建任何密匙。这个称为密匙管理,这是SQL Server可以为你处理一个主要服务。
密匙管理最困难的一部分选择正确的加密。历史上有很多密匙被拦截后,有很多国家秘密被破解。在二战期间,美国、英国和其它联盟国家把大量资源放入截取德国和日本的加密密匙,这样的话,他们可以截取并得到高机密的信息。在最近,很多安全性的应用程序被瓦解,因为攻击能找到在应用程序里或电脑上嵌入的密匙。安全共享秘密非常困难。
你可以自己管理SQL Server加密密匙,如果你选择使用密码,那秘密保存好密匙就是你的责任。大多数人不想这样做,因为它需要高度专业的技术技能。但如果你想承担任务,当你创建密匙时直接使用密码选项。密码就是基本的密匙,你要确保你可以安全的地方保存这个密匙,当你需要它的时候,可以密码传输它。
但你没必要处理这些细节,因为SQL Server会为你管理好密匙。它会为你加密新的密匙,使用你指定的任何方法作为CREATE语句的一部分,安全保存数据如同它保存任何敏感信息。
你有管理密匙的选项,但没事就不要乱动。
加密数据
现在我们来看一个在SQL Server里加密的一个例子。在这个场景里,Customer表有一些客户的常规信息。一些信息,例如客户名称和它们所在的城市,不是敏感的数据,不值得加密。其它数据,例如信用卡类型和号码及备注会包含特定敏感的个人信息,需要加密。
你会使用对称密匙来加密表的数据,但记住对称密匙需要数据库里一个证书或非对称密匙来保护它。因此,首先使用代码8.2来创建保护对称密匙的非对称密匙。
1 CREATE ASYMMETRIC KEY User1AsymmetricKey 2 AUTHORIZATION User1 3 WITH ALGORITHM = RSA_2048
代码8.2:创建使用RSA 2048位算法,属于User1的非对称密匙。
非对称密匙称为User1AsymmetricKey,AUTHORIZATION子句指定User1拥有密匙。这个密匙使用2048位的RSA加密,非常强的加密。这个必须是真的,真的重要数据!
接下来,使用代码8.3出阿健对称密匙User1SymmetricKey。(你必须为你的密匙取更有描述性的名称!)。在这个例子里,它使用TRIPLE_DES算法,用你刚创建的非对称密匙保护它。
1 CREATE SYMMETRIC KEY User1SymmetricKey 2 WITH ALGORITHM = TRIPLE_DES 3 ENCRYPTION BY ASYMMETRIC KEY User1AsymmetricKey;
代码8.3:创建使用Triple DES算法的对称密匙,用刚才的非对称密匙。
如果你想在数据库列出对称的加密密匙,你可以使用sys.symmetric_keys目录视图来查看它们。代码8.4生成了如插图8.2所示的结果。注意,因为数据库主密匙是对称密匙,他在列表里也显示了,你可以看到它用AES_256加密的。
1 SELECT * FROM sys.symmetric_keys;
代码8.4:在数据库列出对称密匙
插图8.2:查看 sys.symmetric_keys目录视图
代码8.5展示了EncryptionDB数据库里的表结构。(这个创建表的代码和刚才初始化环境代码是一样的):
1 CREATE TABLE Customer ( 2 CustId int, 3 Name nvarchar(30), 4 City varchar(20), 5 CreditCardType varbinary(1000), 6 CreditCardNumber varbinary(1000), 7 Notes varbinary(4000));
代码8.5:创建Customer表,varbinary字段用来加密数据。
注意,因为最后三个字段会包含字节流的原始字符数据的加密数据,字段类型是varbinary类型。字段长度取决于数据的大小和保护它的算法。数据库有User1用户,它在表上有SELECT和INSERT许可。
最后,是时候加密一些数据了,我们忘表里插入一些数据。第一步使用如代码8.6的语句打开对称密匙。这一步让SQL Server从内部获得密匙,请确定用户有用这个密匙的许可,然后解密密匙到内存就可以开始使用了。
1 OPEN SYMMETRIC KEY User1SymmetricKey 2 DECRYPTION BY ASYMMETRIC KEY User1AsymmetricKey;
代码8.6:第一步使用对称密匙,使用OPEN SYMMETRIC KEY打开它
数据加密使用T-SQL的EncryptByKey函数,它生成唯一的GUID来标识密匙。你可以使用Key_GUID函数来获得GUID,而不必自己直接传入值。代码8.7是常规的T-SQL插入语句,往表里插入一些数据。
1 INSERT INTO Customer VALUES (1, 'Sally Roe', 'Chatinika', 2 EncryptByKey(Key_GUID('User1SymmetricKey'), 'Visa'), 3 EncryptByKey(Key_GUID('User1SymmetricKey'), '1234-5678-9009-8765'), 4 EncryptByKey(Key_GUID('User1SymmetricKey'), 5 'One of our best customers. Treat like royalty.'));
代码8.7:插入加密数据到表,使用EncryptByKey和Key_GUID函数。
最后一步是关闭对称密匙,使用代码8.8。这个会从内存移除密匙,释放这些资源给其它用户。你应该经常在用完后就关闭密匙,因为它留在内存里的话,就会被不小心被攻击者利用。
1 CLOSE SYMMETRIC KEY User1SymmetricKey;
代码8.8:CLOSE SYMMETRIC KEY语句关闭密匙,从内存中移除它。
提示:
如果你要在批处理里使用加密和解密很多数据,可以留着它打开。打开和关闭密匙需要一点处理,这样的话你可以更高效。但不要忘记关闭它在你完成的时候!
现在运行SELECT语句看看表里有什么,如插图8.3所示。你可以看到在没加密字段看到明文,但加密字段是随机的字节流数据。你的数据现在是安全的!
插图8.3:在表里存储的加密数据。
在表里的数据是毫无用处的,除非有方法取出它。在这个例子里,你需要使用常规的SELECT语句,使用DecryptByKey函数来解密数据。这个函数返回varbinary数据,以为加密数据可以是任何数据类型。因此获得原始文本需要DecryptByKey函数的转化结果为合适的文本字符。
代码8.9打开密匙,运行SELECT语句。
1 OPEN SYMMETRIC KEY User1SymmetricKey 2 DECRYPTION BY ASYMMETRIC KEY User1AsymmetricKey; 3 SELECT CustID, Name, City, 4 CONVERT(VARCHAR, DecryptByKey(CreditCardType)) AS CardType, 5 CONVERT(VARCHAR, DecryptByKey(CreditCardNumber)) AS CardNumber, 6 CONVERT(VARCHAR, DecryptByKey(Notes)) AS Notes 7 FROM Customer; 8 CLOSE SYMMETRIC KEY User1SymmetricKey;
代码8.9:打开对称密匙,然后使用DecryptByKey函数的SELECT语句获得加密数据
这会显示如插图8.4的结果。
插图8.4:使用SELECT和DecryptByKey后的解密数据
提示:
相同的EncryptByAsymKey,EncryptByCert和其它方法都可以用作其它密匙,都有对应的Decrypt函数。
小结
SQL Server的数据加密功能为你的数据提供了额外一层保护,给你在全面的深度保护。像老的中世纪城堡有多层的要塞,SQL Server攻击者需要突破网络安全,服务器安全,SQL Server实例安全和数据库安全才可以拿到你的数据。然后,胜利就在眼前,它们还要处理数据强悍加密来拿到有用的数据。加上强悍的数据库安全,使用细微度的许可来提供最小特权,让主体只能访问它们需要的数据,你可以为你最敏感的数据建立坚不可摧的保护。
原文链接:
http://www.sqlservercentral.com/articles/Stairway+Series/123777/