在与Summit安全小组的成员一起进行安全研究的过程中,我们遇到了一个依赖于TDS(Tabular Data Stream,表格数据流)协议实现加密功能的应用程序。该协议的功能是在Microsoft SQL Server中实现的,用来加密在不可信网络中的通信。出于好奇,我们仔细研究了如果在服务器和客户端上修改不同的配置,是否会对该协议的安全性产生影响。最后研究表明,借助该协议通信时,客户端的通信存在着安全风险。为证明这一风险,我们开发了一个中间人(MitM)工具,该工具利用了两个不同的不安全配置来实现攻击。我们希望这篇文章能提醒大家,在使用TDS加密时,一定要进行正确的配置。
背景
表格数据流(TDS)协议被Microsoft SQL Server广泛使用,是其客户端与数据库服务器进行交互的主要方式。多年来,该协议已经进行了多次升级,不断增加了对其他功能的支持,包括支持使用TLS作为随机加密的方式。这种随机加密的实现与STARTTLS类似。在一开始,会进行未加密的初始握手,如果双方都支持加密,则会在同一TCP连接上发生TLS握手,随后在此加密隧道上进行后续通信。然而,与其他随机加密一样,如果客户端和服务器没有经过正确配置,该协议很可能受到降级攻击以及其他中间人攻击。更严重的一个问题是,在关于这一部分的微软官方技术文档中,并没有进行清晰、正确的描述,这样一来就更容易使用户进行错误的配置。
攻击方式1:证书伪造
在使用TLS的过程中,我们必须关注证书的验证过程。攻击者可能首先针对TLS尝试实施中间人攻击,尝试使用一个伪造的证书欺骗TLS客户端以及服务器(如果客户端证书正在使用)。比较让人放心的是,微软对于TDS协议的使用过程是安全的,它默认会对证书进行验证,从而防止这类的攻击。只有在开发人员手动在配置中禁用了证书验证的情况下,才会存在风险。然而,为方便开发与调试,开发人员经常会选择在非生产环境中不使用证书,所以在安全评估过程中,需要特别注意,确保实际生产环境中启用了证书验证。针对这一种攻击方式,我们开发了一个工具,可以测试TDS是否启用证书验证。
我们的TDS中间人攻击脚本可以通过“–mitm_type”的选项以“证书模式”运行。这时,脚本就会自动执行经典的证书中间人攻击,即从客户端接受TLS连接,在握手完成之前,向服务器发起第二次攻击。该脚本利用了Bletchley SSL/TLS库自动复制服务器生成的证书,并向客户端提供一个伪造的证书。
攻击方式2:非对称降级攻击
当TDS客户端连接到Microsoft SQL Server时,会进行一次未加密的握手,在这次握手过程中双方会通知是否将使用加密。客户端与服务器双方,都可以进行如下声明:不支持加密(ENCRYPT_NOT_SUP)、支持加密但不希望使用(ENCRYPT_OFF)、支持加密并希望使用(ENCRYPT_ON)、强制使用加密(ENCRYPT_REQ)。其中,前三个选项充分考虑到了对低版本的兼容性,但我们从安全的角度来看,显然只有第四个选项是安全的。如果任何一方都不明确要求加密,那么攻击者可以进行中间人攻击,篡改双方握手消息中的一个值,让其中一方误认为对方不支持加密。这样一来,客户端和服务器都会认为对方不支持加密,从而就会进行不安全的通信。这个应用于TDS的经典降级攻击方式,曾经在2015年由Azhar Desai进行过详细说明。但这一问题还没有结束,我们试想,如果一方要求使用加密,另一方不要求使用加密,会发生什么?这种情况下是否还能被攻击呢?
经过验证,答案是肯定的。在服务器要求使用加密,但客户端不支持加密的情况下,非对称降级攻击非常容易进行。我们已经知道,在最早的握手数据包中,服务器将会通告ENCRYPT_REQ,试图向客户端发送“必须使用加密”的信号。同时,客户端则会通告ENCRYPT_ON或ENCRYPT_OFF。在攻击过程中,攻击者修改服务器发出的握手包,将其设置为ENCRYPT_NOT_SUP,这样一来就会使客户端在接下来的通信中禁用加密。然而,服务器并不了解这一情况,仍然在等待着接下来的TLS握手。此时,如果攻击者冒充客户端并发起TLS握手,由于服务器并不需要任何TLS客户端证书(在TDS中只有服务器证书会被验证),因此服务器无法判断出假冒的客户端,会继续与冒充客户端的攻击者进行通信。
接下来,攻击者只需要传递双方之间的通信。由于消息通过TLS通道从服务器发出,因此它们会被解密,并通过未加密的TDS连接转发给客户端。同样的,在客户端将未加密的消息发送给攻击者后,攻击者会通过TLS连接将其转发给服务器。而这些通信之中,通常会包含客户端的密码认证握手,可能会暴露数据库用户的密码Hash值,甚至是明文密码。
我们用下面的图示来总结了此次攻击的步骤。在下图中,展现的是未经篡改的握手过程,客户端希望使用加密(但不必须),服务器也要求必须使用加密:
由于客户端不强制要求加密,因此这样的通信过程容易受到攻击,其中间人攻击的示意图如下:
在使用我们的TDS中间人攻击脚本时,可以通过“–mitm_type”的选项以“降级模式”运行,脚本就会自动进行这种攻击。
但是,我们还要考虑一种情况,如果TDS客户端要求必须加密,但服务器并不必须呢,这时还有可能发生攻击吗?由于TLS只会在一个方向上被认证,因此这种情况与之前并不相同。如果客户端要求使用加密,并且正在验证该连接上的服务器证书(假设在配置中未禁用“证书验证”),那么这一连接将无法被攻击。尽管攻击者可以通过中间人的方式,欺骗服务器使用不加密的方式,但攻击者并不能使用一个无效的服务器证书去欺骗客户端。
事实证明,在使用TLS来保证安全性的TDS通信中,我们实际上只需要关注两件事:一是客户端应配置为“必须使用加密”,二是客户端应配置为“验证服务器证书”。我们意识到,在这里所谓的“兼容性”,反而给用户增加了安全上的风险。
官方文档的误导
在研究过程中,我们还阅读了微软提供的大量文档,但却发现,其中的许多文档误导了开发人员,使他们错误地认为一些配置是安全的,甚至还包含一些安全关键细节的错误陈述。在这里,我们详细列出这些错误,并希望微软能修改这部分内容,以避免对MSSQL用户造成误导。
(1) 在一篇已经过时的文章《如何使用Microsoft管理控制台为SQL Server实例启用SSL加密》中,特别强调了如下建议:“不要同时在客户端和服务器上启用强制协议加密选项。要在服务器上启用强制协议加密,请根据SQL Server的版本,选择使用服务器网络实用程序(Server Network Utility)或SQL Server配置管理器。要在客户端上启用强制协议加密,请使用客户端网络实用程序(Client Network Utility)或SQL Server配置管理器。”这段建议的内容存在一些问题,因为只有同时在客户端和服务器上进行加密,才能有效。另外,我们现在已经知道,服务器端的设置与安全无关。
(2) 在《启用到数据库引擎的加密连接》文章的“配置服务器允许加密连接”章节中,详细讲解了如何将服务器配置为强制需要加密的方法。然而,该章节的标题中“允许”这一词不太妥当,因为SQL Server默认就是允许加密连接的,只是在默认情况下没有强制要求。 此外,这样的设置并不会额外增加通信的安全性,该文章却没有表明这一点。
(3) 在微软最近的一篇文章《使用未经验证的加密》中,存在大量误导以及表述错误,需要我们在此详细列举。
a. 首先,文章的标题本身就存在明显的问题。 在没有证书验证的情况下使用TLS,与我们使用加密的根本目的相违背。 我们强烈建议微软在文章中明确作出提醒,以突出这一事实。
b. 在这篇文章中的第一句话也存在问题:“SQL Server总会对与登录相关的网络数据包进行加密”。其中并没有提到加密的握手是基于NTLM身份验证,而我们知道,NTLM身份验证几十年来始终存在着缺陷,从而产生中继攻击(Relay attacks)和离线密码破解的风险。 更糟糕的是,最近有研究表明,密码认证握手本身就可能被降级攻击,该攻击将导致允许进行完整的明文密码检索。甚至,在Metasploit中,还有一个专门为进行这些攻击而设计的模块。最后,即使这个密码认证握手过程是安全的,攻击者也可以在认证完成后劫持TCP连接,并获得与合法客户端相同的访问权限。
c. 在下一段中,有如下表述:“这也可以由SQL Server配置管理器使用‘强制协议加密选项’进行配置。”就像前一篇文章中的错误表述一样,服务器端的设置并不会增加安全性。
d. 后文中还有:“如果要在服务器未配置证书的情况下启用加密,可以使用SQL Server配置管理器,设置强制协议加密和信任服务器证书这两个选项。在这种情况下,如果服务器没有预先配置可验证的证书,将使用未经验证的自签名服务器证书。”其中,最后一句话非常容易产生误导。如果在客户端上设置了信任服务器证书选项,那么通信会非常容易受到证书中间人攻击,即使后面再在服务器上部署可验证的证书也一样。这样的表述,可能让用户误认为修复方式只是部署一个可验证的证书,而不需要将客户端的设置也修改正确。
e. 这篇文章提供了一个服务器和客户端设置的详细列表,并描述了在每种情况下会发生什么,能够帮助我们更深入地理解其工作机制。然而,文章中反复强调了在没有证书验证的情况下可以使用加密,并且比不使用加密要更安全,而事实却并非如此。假如拥有正确的工具,发起一次主动的中间人攻击,就像我们如今进行的被动嗅探一样容易。
我们欣慰地看到,微软还是有一些文章,针对这些设置做出了准确的说明。 在《到SQL Server的加密连接》这篇文章中,给出了一个明确的提醒,其原文为:“使用自签名证书加密的SSL连接,不具有强安全性,它们容易受到中间人攻击。在生产环境或是连接到互联网的服务器上,您不应该选择使用自签名证书的SSL连接”。 这是一个非常有效的提醒信息,我认为类似的提醒应该出现在所有与可信服务器证书设置相关的文章之中。除此之外,我希望在这些文章中,还能对强制加密这部分做出提醒。
另外我们看到,Azure团队似乎做足了功课。他们向客户提供的示例中,所有客户端连接字符串都包含明确的TrustServerCertificate = False标志(仅显式启用证书验证)以及需要加密的相应标志。
厂商回应
我们在2017年11月22日联系了微软安全应急响应中心(MSRC),向他们发送了这篇文章的草稿以及我们开发的中间人攻击脚本。我们建议微软对该问题进行验证,更新他们的产品,并对官方文档及相关文章做以修改。MSRC回复了我们的电子邮件,但SQL Server产品团队目前还没有回应。
相关研究
SSL/TLS不对称降级的攻击方式并不是一个新的概念。在五年前,Moxie Marlinspike曾经发布过一个SSLTrip工具,使用的正是该攻击方式。同样,针对STARTTLS的降级攻击也在很早之前就实现过。然而遗憾的是,这些技术在特有的协议上的应用往往是缓慢的。在2016年初进行测试的时候,我们并没有发现有任何工具能针对TDS协议进行降级攻击,同样也没有发现证书欺骗攻击的利用工具。在我们完善这篇文章的过程中,发现了另一个工具TDSBridge,该工具可以作为TDS代理,并且在使用文档中称其“可以在服务器端强制加密”。尽管TSDBridge并不是一个安全工具,但我们还是有必要提到,尽管在该工具的开发过程中,没有将其视为一个安全风险,但该工具还是有助于证明我们此次的发现。
总结
由于客户端库无需加密,所以在默认配置下,Microsoft SQL Server数据库的通信并不安全。 因此,需要我们对服务器证书进行正确的配置。 然而,用于指导管理员如何保证通信安全性的文档,存在多个严重错误,我们强烈建议微软应对其进行修改。基于不安全的默认设置和大量误导性文档这两个事实,我们认为,绝大多数Microsoft SQL Server的网络流量都容易受到中间人攻击,这一点需要特别引起大家的重视。
发表评论
您还未登录,请先登录。
登录