集团新闻

    背景

    表格数据流(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_ONENCRYPT_OFF。在攻击过程中,攻击者修改服务器发出的握手包,将其设置为ENCRYPT_NOT_SUP,这样一来就会使客户端在接下来的通信中禁用加密。然而,服务器并不了解这一情况,仍然在等待着接下来的TLS握手。此时,如果攻击者冒充客户端并发起TLS握手,由于服务器并不需要任何TLS客户端证书(在TDS中只有服务器证书会被验证),因此服务器无法判断出假冒的客户端,会继续与冒充客户端的攻击者进行通信。

    接下来,攻击者只需要传递双方之间的通信。由于消息通过TLS通道从服务器发出,因此它们会被解密,并通过未加密的TDS连接转发给客户端。同样的,在客户端将未加密的消息发送给攻击者后,攻击者会通过TLS连接将其转发给服务器。而这些通信之中,通常会包含客户端的密码认证握手,可能会暴露数据库用户的密码Hash值,甚至是明文密码。

    在使用我们的TDS中间人攻击脚本时,可以通过“–mitm_type”的选项以“降级模式”运行,脚本就会自动进行这种攻击。

    但是,我们还要考虑一种情况,如果TDS客户端要求必须加密,但服务器并不必须呢,这时还有可能发生攻击吗?由于TLS只会在一个方向上被认证,因此这种情况与之前并不相同。如果客户端要求使用加密,并且正在验证该连接上的服务器证书(假设在配置中未禁用“证书验证”),那么这一连接将无法被攻击。尽管攻击者可以通过中间人的方式,欺骗服务器使用不加密的方式,但攻击者并不能使用一个无效的服务器证书去欺骗客户端。

    事实证明,在使用TLS来保证安全性的TDS通信中,我们实际上只需要关注两件事:一是客户端应配置为“必须使用加密”,二是客户端应配置为“验证服务器证书”。我们意识到,在这里所谓的“兼容性”,反而给用户增加了安全上的风险。