TLS安全重协商

2024-08-23 19:59:56 浏览数 (3)

TLSrenegotiation

TLS安全重协商

在TLS安全重协商出来前,有一个TLS重协商的漏洞,它会被中间人攻击利用,可以插入非法数据到客户端和服务器的安全连接中。虽然这个漏洞无法被用来破解密钥,但是可以用来插入恶意数据,比如在HTTPS中插入恶意的JavaScript代码。该漏洞在2009年的时候被发现,但是直到2011年才被修复,修复的方案就是本文要介绍的“安全重协商”。

重协商漏洞

重协商的有两种方式:

  1. 客户端可以在TLS连接建立后,发送一个ClientHello消息去示意服务器开启重协商,如果服务器同意的话就会回复ServerHello开启新的握手,这个过程是可以无限重复的。
  2. 服务器可以在TLS连接建立后,发送一个HelloRequest消息去示意客户端开启重协商,如果客户端同意的话就会回复ClientHello开启新的握手,这个过程是可以无限重复的。

重协商的漏洞的根本原因是,重协商的消息没有跟已经建立的TLS连接绑定,因此服务器无法鉴别ClinetHello是否来自真实客户端的,会误以为是客户端发起的重协商,从而导致中间人攻击。其攻击过程大致如下:

重协商漏洞

安全重协商

那么引入的“安全重协商”是如何解决该问题的呢?我们前面讲到,根本问题是服务器无法鉴别ClientHello是否来自同一个客户端,即没有做到绑定两次协商,因此解决方案就是完成绑定,具体绑定方法可以从下面安全重协商过程中得到答案:

安全重协商

如上所示,在ClientHelloServerHello中引入了新的扩展renegotiation_info。客户端如果支持安全重协商就在扩展中携带renegotiation_info扩展,而服务器如果接受安全重协商就在ServerHello扩展中携带renegotiation_info扩展以作为回应,当然如果服务器不想支持的话就不需要携带,这样客户端就知道服务器不想支持了。

在初始协商即Hello的过程中,该扩展的内容应该为空,即数据大小为0,否则应当立刻返回fatal_alert。细心的同学应该看到了,在ClientHello中还有一个“CSCV(Signaling Cipher Suite Value)”的值,实际的值是TLS_EMPTY_RENEGOTIATION_INFO_SCSV,它是一个信令套件,主要作用是:

  1. 为了兼容那些不支持扩展的协议版本,比如SSLv3TLS1.0,这些协议版本不支持扩展,因此无法携带renegotiation_info扩展,但是它们发送信令套件。
  2. 因为有些TLS服务器会去检查扩展类型,并且对不支持的扩展会按错误处理,而不是忽略,但是它们会忽略不支持,因此使用信令套件可以兼容这种场景。后向兼容SSLv2可看 Appendix E.2 of [RFC5246]

虽然没有规定客户端必须用哪一种方式,甚至可以一起用,但是建议是客户端使用“CSCV”,因为兼容性更好。

在Hello交互后,双方都应该记录重协商的状态,即如果支持则renegotiation_flag=1,反之renegotiation_flag=0

接下来会继续完成剩余的握手过程,区别是如果renegotiation_flag=1的话,客户端和服务器双方都必须记录下来自Finished消息的client_verify_dataserver_verify_data,以便下次重协商时使用。

当客户端准备发起重协商时,它会在ClientHello中携带renegotiation_info扩展,值为client_verify_data,服务器收到后必须确保:

  • 在该消息中没有包含TLS_EMPTY_RENEGOTIATION_INFO_SCSV,如果有,应该返回一个fatal_alert
  • 必须确保该消息包含renegotiation_info扩展,且值为client_verify_data

这里我们可以看到,重协商跟上一个TLS会话做了绑定,因此服务器可以鉴别ClientHello是否来自同一个客户端,从而防止中间人攻击。

如果服务器接收重协商,那么服务器发送ServerHello,包含renegotiation_info扩展,值包含server_verify_dataclient_verify_data

客户端收到了新的ServerHello并核对renegotiation_info扩展的值是否正确(跟自己记录的server_verify_dataclient_verify_data做比对,看是否相等),这里也可以看到,重协商跟上一个TLS会话绑定,因此客户端可以鉴别ServerHello是否来自同一个服务器,并且可以知道服务器是否有受到攻击,从而防止中间人攻击。

最后正常进行后续握手,在握手完成后客户端和服务器必须保存新的client_verify_dataserver_verify_data,以便下次重新协商时使用。

有了这样的绑定,中间人将无处可破:

安全重协商攻击

开发细节

新增了三种连接状态值:

  1. secure_renegotiation flag(上文中提到的renegotiation_flag
  2. client_verify_data:来自客户端的 Finished 消息
  3. server_verify_data:来自服务器的 Finished 消息

新增扩展类型renegotiation_info,其值为0xff01 新增的信令套件TLS_EMPTY_RENEGOTIATION_INFO_SCSV,其值为{0x00, 0xFF}

数据结构为:

代码语言:javascript复制
struct {
    // renegotiated_connection_length
    opaque renegotiated_connection<0..255>;
} RenegotiationInfo;

扩展的值为:

  1. 如果是在初始化的ClientHelloServerHello中,它们的值都是0长度的,因此它的值固定为ff 01 00 01 00
    • 1、2字节 扩展类型
    • 3、4字节为扩展长度
    • 5字节表达重新协商的连接长度,这里是0
  2. 如果是正在重新协商的ClientHellos,那么它会包含client_verify_data
  3. 如果是正在重新协商的ServerHellos,那么它会包含client_verify_dataserver_verify_data。对于当前版本,这个是24字节值,对于SSLv3,它是一个72字节值。

它可以跟DTLS [RFC4347]一起使用。

总结协商步骤:

  1. 客户端发送ClientHello,包含renegotiation_info扩展或信令套件TLS_EMPTY_RENEGOTIATION_INFO_SCSV,如果是renegotiation_info扩展,值应该是0长度的。
    • 不建议两个都发送
  2. 服务器收到了renegotiation_infoTLS_EMPTY_RENEGOTIATION_INFO_SCSV后,如果接受重新协商,应当返回一个renegotiation_info扩展,值应该是0长度的。并且设置secure_renegotiationTRUE
    • 如果收到的是reneogtiation_info扩展,那么应该判断它是否是0长度,否则返回一个fatal_alert
  3. 正常进行握手及数据通信。
  4. 如果客户端要重新协商,则发送一个ClientHello,包含renegotiation_info扩展,值为client_verify_data
  5. 服务器接收到ClientHello后,必须确保:
    • 在该消息中没有包含TLS_EMPTY_RENEGOTIATION_INFO_SCSV,如果有,应该返回一个fatal_alert
    • 必须确保该消息包含renegotiation_info扩展,且值为client_verify_data
  6. 服务器发送ServerHello,包含renegotiation_info扩展,值包含server_verify_dataclient_verify_data
  7. 客户端收到了新的ServerHello并核对renegotiation_info扩展的值是否正确(server_verify_dataclient_verify_data
  8. 正常进行握手,在握手完成后客户端和服务器必须保存新的client_verify_dataserver_verify_data,以便下次重新协商时使用。

(非安全)重协商处置方式:

  1. 客户和服务器都直接拒绝
  2. 客户端收到HelloRequest后,在新的ClientHello中应该包含renegotiation_info扩展或TLS_EMPTY_RENEGOTIATION_INFO_SCSV
  3. 服务器收到ClientHello必须确保没有TLS_EMPTY_RENEGOTIATION_INFO_SCSV,如果有就必须返回一个fatal_alert
  4. 服务器必须确保客户端扩展包含一个renegotiation_info扩展,如果没有就必须返回一个fatal_alert

OPENSSL相关选项:

  • 开启重协商:SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
  • 禁用协商:SSL_OP_NO_RENEGOTIATION

引用

  • 安全重协商:RFC 5746

1 人点赞