TLSrenegotiation
TLS安全重协商
在TLS安全重协商出来前,有一个TLS重协商的漏洞,它会被中间人攻击利用,可以插入非法数据到客户端和服务器的安全连接中。虽然这个漏洞无法被用来破解密钥,但是可以用来插入恶意数据,比如在HTTPS中插入恶意的JavaScript代码。该漏洞在2009年的时候被发现,但是直到2011年才被修复,修复的方案就是本文要介绍的“安全重协商”。
重协商漏洞
重协商的有两种方式:
- 客户端可以在TLS连接建立后,发送一个
ClientHello
消息去示意服务器开启重协商,如果服务器同意的话就会回复ServerHello
开启新的握手,这个过程是可以无限重复的。 - 服务器可以在TLS连接建立后,发送一个
HelloRequest
消息去示意客户端开启重协商,如果客户端同意的话就会回复ClientHello
开启新的握手,这个过程是可以无限重复的。
重协商的漏洞的根本原因是,重协商的消息没有跟已经建立的TLS连接绑定,因此服务器无法鉴别ClinetHello
是否来自真实客户端的,会误以为是客户端发起的重协商,从而导致中间人攻击。其攻击过程大致如下:
重协商漏洞
安全重协商
那么引入的“安全重协商”是如何解决该问题的呢?我们前面讲到,根本问题是服务器无法鉴别ClientHello
是否来自同一个客户端,即没有做到绑定两次协商,因此解决方案就是完成绑定,具体绑定方法可以从下面安全重协商过程中得到答案:
安全重协商
如上所示,在ClientHello
和ServerHello
中引入了新的扩展renegotiation_info
。客户端如果支持安全重协商就在扩展中携带renegotiation_info
扩展,而服务器如果接受安全重协商就在ServerHello
扩展中携带renegotiation_info
扩展以作为回应,当然如果服务器不想支持的话就不需要携带,这样客户端就知道服务器不想支持了。
在初始协商即Hello的过程中,该扩展的内容应该为空,即数据大小为0,否则应当立刻返回fatal_alert
。细心的同学应该看到了,在ClientHello
中还有一个“CSCV(Signaling Cipher Suite Value)”的值,实际的值是TLS_EMPTY_RENEGOTIATION_INFO_SCSV
,它是一个信令套件,主要作用是:
- 为了兼容那些不支持扩展的协议版本,比如
SSLv3
和TLS1.0
,这些协议版本不支持扩展,因此无法携带renegotiation_info
扩展,但是它们发送信令套件。 - 因为有些TLS服务器会去检查扩展类型,并且对不支持的扩展会按错误处理,而不是忽略,但是它们会忽略不支持,因此使用信令套件可以兼容这种场景。后向兼容
SSLv2
可看 Appendix E.2 of [RFC5246]
虽然没有规定客户端必须用哪一种方式,甚至可以一起用,但是建议是客户端使用“CSCV”,因为兼容性更好。
在Hello交互后,双方都应该记录重协商的状态,即如果支持则renegotiation_flag=1
,反之renegotiation_flag=0
。
接下来会继续完成剩余的握手过程,区别是如果renegotiation_flag=1
的话,客户端和服务器双方都必须记录下来自Finished
消息的client_verify_data
和server_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_data
和client_verify_data
。
客户端收到了新的ServerHello
并核对renegotiation_info
扩展的值是否正确(跟自己记录的server_verify_data
和client_verify_data
做比对,看是否相等),这里也可以看到,重协商跟上一个TLS会话绑定,因此客户端可以鉴别ServerHello
是否来自同一个服务器,并且可以知道服务器是否有受到攻击,从而防止中间人攻击。
最后正常进行后续握手,在握手完成后客户端和服务器必须保存新的client_verify_data
和server_verify_data
,以便下次重新协商时使用。
有了这样的绑定,中间人将无处可破:
安全重协商攻击
开发细节
新增了三种连接状态值:
secure_renegotiation
flag(上文中提到的renegotiation_flag
)client_verify_data
:来自客户端的Finished
消息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;
扩展的值为:
- 如果是在初始化的
ClientHello
和ServerHello
中,它们的值都是0长度的,因此它的值固定为ff 01 00 01 00
:- 1、2字节 扩展类型
- 3、4字节为扩展长度
- 5字节表达重新协商的连接长度,这里是0
- 如果是正在重新协商的
ClientHello
s,那么它会包含client_verify_data
- 如果是正在重新协商的
ServerHello
s,那么它会包含client_verify_data
和server_verify_data
。对于当前版本,这个是24字节值,对于SSLv3,它是一个72字节值。
它可以跟DTLS [RFC4347]一起使用。
总结协商步骤:
- 客户端发送
ClientHello
,包含renegotiation_info
扩展或信令套件TLS_EMPTY_RENEGOTIATION_INFO_SCSV
,如果是renegotiation_info
扩展,值应该是0长度的。- 不建议两个都发送
- 服务器收到了
renegotiation_info
或TLS_EMPTY_RENEGOTIATION_INFO_SCSV
后,如果接受重新协商,应当返回一个renegotiation_info
扩展,值应该是0长度的。并且设置secure_renegotiation
为TRUE
- 如果收到的是
reneogtiation_info
扩展,那么应该判断它是否是0长度,否则返回一个fatal_alert
。
- 如果收到的是
- 正常进行握手及数据通信。
- 如果客户端要重新协商,则发送一个
ClientHello
,包含renegotiation_info
扩展,值为client_verify_data
。 - 服务器接收到
ClientHello
后,必须确保:- 在该消息中没有包含
TLS_EMPTY_RENEGOTIATION_INFO_SCSV
,如果有,应该返回一个fatal_alert
。 - 必须确保该消息包含
renegotiation_info
扩展,且值为client_verify_data
。
- 在该消息中没有包含
- 服务器发送
ServerHello
,包含renegotiation_info
扩展,值包含server_verify_data
和client_verify_data
。 - 客户端收到了新的
ServerHello
并核对renegotiation_info
扩展的值是否正确(server_verify_data
和client_verify_data
) - 正常进行握手,在握手完成后客户端和服务器必须保存新的
client_verify_data
和server_verify_data
,以便下次重新协商时使用。
(非安全)重协商处置方式:
- 客户和服务器都直接拒绝
- 客户端收到
HelloRequest
后,在新的ClientHello
中应该包含renegotiation_info
扩展或TLS_EMPTY_RENEGOTIATION_INFO_SCSV
。 - 服务器收到
ClientHello
必须确保没有TLS_EMPTY_RENEGOTIATION_INFO_SCSV
,如果有就必须返回一个fatal_alert
。 - 服务器必须确保客户端扩展包含一个
renegotiation_info
扩展,如果没有就必须返回一个fatal_alert
。
OPENSSL相关选项:
- 开启重协商:
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
- 禁用协商:
SSL_OP_NO_RENEGOTIATION
引用
- 安全重协商:RFC 5746