0371-63319761
您的当前位置:主页 > 安全研究 > 安全研究 >

谈谈安全传输层协议-TLS

时间:2021-04-26


TLS,Transport Layer Security ,起源于1994年由Netscape开发的SSL协议,后经IETF标准化后于1999年推出第一版TLS标准文件,即TLS1.0。经过二十多年的发展,TLS陆续派生出TLS1.1(RFC4346)、TLS1.2(RFC5246)、TLS1.3(RFC8446)。其中TLS1.2目前应用最广,支持程度最高。后面的介绍也主要围绕TLS1.2展开。 
 
TLS的优势建立在两个方面:(1)基于密码学的TLS能够完美的实现通信双方的身份认证、应用数据加密;(2)与上层的应用协议无耦合,应用层协议能透明地运行在TLS协议构建的安全通道之上。
 
1. TLS组成

如图1所示,TLS由记录层(记录协议)和握手协议层(握手协议、密钥变更协议、告警协议)组成。
 

图1.  TLS协议组成
 
 2. 记录层协议

由于UDS功能十分强大,可以直接对车辆电子控制进行配置更改、功能测试、中断、重启、读取及写入数据等操作,车辆一旦在行驶中遭到UDS恶意攻击,将直接导致ECU及其关联系统的失效,篡改甚至被恶意操控。
 
记录协议承载被发送的数据,将数据分片为可管理的块、有选择地压缩(可选)、应用MAC、加密并交付给下层协议,对于接收到的数据进行解密、验证、解压缩(可选)、重组,然后传递给上层协议。记录协议是一个层次化的协议,在每一层中,消息都包含长度、版本、类型。特别需要注意的是一个记录消息的类型和长度不能使用加密保护。
 

图2 TLS记录层
 
记录协议的操作环境也称之为连接状态,一个TLS连接状态包含压缩状态(压缩算法的当前状态)、加解密钥状态(加密算法的当前状态,这个状态由连接的预定密钥组成。对于流密码,这个状态也将包含对流数据进行加解密所需的任何必要的状态信息)、MAC密钥状态(当前连接的MAC密钥)、序列号(读和写状态分别维持一个序列号, 类型是uint64,所以序列号大小不会超过2^64-1。当一个连接的状态被激活时序列号必须置为0。序列号不能回绕,如果一个TLS实现需要回绕序列号,则必须重新协商。一个序列号在每条记录信息被发送之后增加。特别地,在一个特殊连接状态下发送的.第一条记录消息必须使用序列号0)。连接状态中算法的参数必须是已知的,用于连接的读、写两个方向的MAC密钥和块加密密钥(注意,TLS连接读写方向使用的是完全不同的两套密钥)。一旦接收到对端的 ChangeCipherSpec 消息以后,Client 和 Server的状态就会转变。
 
那么问题来了,连接状态转变是根据什么转变的呢?这里又涉及到另外一个概念,安全参数(Security parameter)。一个TLS连接读写状态的安全参数可以通过提供如下值来设定:
 
1. 连接终端: 在这个连接中这个实体被认为是“client”或“server”。
 
2. PRF算法: 被用于从主密钥生成密钥的算法。
 
3. 块加密算法: 被用于块加密的算法。本规范包含了这种算法的密钥长度,它是成块加密,流加密,或AEAD加密,密文的块大小(如果合适的话),和显示和隐式初始化向量 (或nonces)的长度
 
4. MAC算法: 被用于消息验证的算法。本规范包含了MAC算法返回值的长度。
 
5. 压缩算法: 用于数据压缩的算法。被规范必须包含算法执行压缩所需的所有信息。
 
6. 主密钥: 在连接的两端之间共享的48字节密钥。
 
7. 客户端随机数: 由客户端提供的32字节随机数。
 
8. 服务器随机数: 由服务器提供的32字节随机数。
 
Server端接收并处理记录时会使用Client写参数,反之亦然。一旦安全参数被设定且密钥被生成,连接状态就可以将它们设置为当前状态来进行初始化。TLS握手协议的主要作用就是为了填充安全参数。
 
3. 密钥变更协议
 
变更密码规范协议存在的目的是通告加密策略的改变,可以被client和server发送,以通告接收方随后的记录消息将会由新协商的密码规范和密钥所保护。注意:如果发生一个重握手事件而连接的数据还在流动,通信的双方可能使用旧的CipherSpec继续发送数据。然而,一旦ChangeCipherSpec被发送了,新的CipherSpec必须被使用。先发送ChangeCipherSpec的一方不知道另外一方已经完成了新密钥数据的计算(例如,如果它执行一个耗时的公钥操作)。因此,在接收方必须缓存数据时会存在一个小的窗口时间。事实上,在现代机器中这个间隔会相当短。
 
4. 告警协议
 
告警消息传递了消息的严重程度(警告或致命)和告警的描述。致命消息发送后立马处理,服务端和客户端必须忘记任何会话描述符、密钥、失败连接相关的机密信息。因此,任何一个被一个致命警报终结的连接都不能被恢复。对于非致命消息,接受方或者发送方有完全的能力决定是否发送或接受错误,或对错误进行进一步处理,如接收方完全可以发送一个致命警报终结连接或选择忽略继续连接。鉴于此,发送方通常不会知道接收方会有何行为。
 
如下类型的错误警报:
 
● unexpected_message:收到一个不合适的消息。这个警报一直是致命类型且不应该在正确的实现之间被观察到。
 
● bad_record_mac:如果收到一个记录其MAC是不正确的,则会返回这种警报。当因为一个TLSCiphertext以不正确的方式解密(或者它不是块长度的偶数倍,或它的填充值被检查出不正确)而发送一个警报时此类警报也必须发送。这个消息通常是致命类型并且不应该在正确的实现之间被观察到(除非消息在网络中损坏)。
 
● decryption_failed_RESERVED:这种警报被用于一些早期版本的TLS,且可能导致针对CBC模式的特定攻击。在兼容型实现中不能发送此消息。
 
● record_overflow:收到一个TLSCiphertext的消息其长度大于2^14+2048字节,或一个记录被解密为TLSCompressed后其长度大于2^14+1024字节。这个消息通常是致命类型并且不应该在正确的实现之间被观察到(除非消息在网络中损坏)。
 
● decompression_failure:解压缩函数收到不正常的输入(例如, 数据扩展为过多的长度).这个消息通常是致命类型并且不应该在正确的实现之间被观察到(除非消息在网络中损坏)
 
● handshake_failure:收到 handshake_failure警报消息意味着在给定选项时发送方不能协商一个可接受的安全参数集。这是个致命错误。
 
● no_certificate_RESERVED:这个警报用于SSLv3但不是任何版本的TLS。在兼容型实现中不能发送此消息。
 
● bad_certificate:证书被损坏,包含的签名无法正确验证等。
 
● unsupported_certificate:证书是不支持的类型
 
● certificate_revoked:证书被其签名者撤销
 
● certificate_expired:证书过期或当前无效
 
● certificate_unknown:在处理证书时产生了一些其它(未指定)问题,导致其无法接受
 
● illegal_parameter:在握手阶段一个域的值超出合法范围或与其它的域不一致。这个消息一直是致命的。
 
● unknown_ca:一个有效的证书链或部分链被接受,但证书没有被接受,因为CA证书不能被定位或不能与一个知名的、可信任的CA匹配。这个消息一直是致命的。
 
● access_denied:接收到一个有效的证书, 但应用访问控制时, 发送方决定不继续协商. 这个消息一直是致命的。
 
● decode_error:由于一些域超出指定范围或消息长度不正确导致消息不能被解码. 这个消息通常是致命类型的且绝不能在两个合理的TLS实现之间通信时出现(除非消息在网络中损坏)
 
● decrypt_error:一个握手密文操作失败, 包括不能正确验证签名或一个结束消息. 这个消息一直是致命的。
 
● export_restriction_RESERVED:这个alert曾被用于一些TLS的早期版本. 在兼容实现中不能发送此消息.
 
● protocol_version:Client端试图协商的协议版本号版本被支持(例如, 旧的协议版本由于安全原因被废弃). 这个消息一直是致命的。
 
● insufficient_security:当一个协商由于server需要比client能够支持的更安全的算法族而失败时取代handshake_failure消息返回, 这个消息一直是致命的.
 
● internal_error:一个与对端或协议正确性都无关的内部错误(例如内存分配错误)使得协议无法继续执行.这个消息一直是致命的.
 
● user_canceled:这次握手由于一些与协议错误无关的原因被取消.如果在握手完成后用户才取消操作,只通过发送一个close_notify消息来关闭连接更合适. 这个alert应该跟随一个close_notify. 这个消息通常是一个警告.
 
● no_renegotiation:由客户端发送用于响应一个hello请求,或由服务端发送用于在初始化握手时响应一个client hello.二者中的任何一个都通常会导致重协商;当重协商不合适时, 接收端应答用此警报来响应.这时,原始请求者能决定是否继续连接.一种适当的情况是一个server产生一个进程以满足一个请求;这个进程能在启动时接收安全参数(密钥长度,认证等),在这个阶段之后再修改这些参数则可能会很困难.这个消息通常是一个警告.
 
● unsupported_extension:由客户端发送;该客户端接收到了server hello消息中包含的一个扩展,但这些扩展不能被放入相应的client hello消息中.这个消息一直是致命的.
 
5. 握手协议

下图,TLS1.2握手完成安全参数的填充,涉及证书交换、验证,密钥传输/协商。带“*“表示该消息是可选的。
 

图3 TLS1.2握手
 
网上有很多握手协议的描述,在这里不做赘述。只提出几个关键点:
 
(1)TLS有三种认证模式:双方认证,服务器认证,无认证。对于汽车而言,车外通信推荐使用双向认证;
 
(2)CientKeyExchange后会涉及密钥交换的问题,TLS提供了RSA和(EC)DH(E)两类方式。当协议的密钥套件中包含RSA时,客户端独立生成预备主密钥,经过服务器端证书公钥加密后传递为服务器端;当协议的密钥套件中包含(EC)DH(E)时,则由客户端和服务器协商生成预备主密钥;一旦主密钥计算完毕,预主密钥应该立刻从内存中删除;
 
(3)一个TLS连接的读写两个方向上密钥是完全不同的,包括加解密密钥、MAC密钥和初始IV;
 
(4)Finished消息是整个TLS连接中第一个使用加解密密钥加密过的消息,对于客户端核验,会将该Finish消息前的所有消息进行加密传输,如果服务器端解密后与自己的握手状态信息进行对比,如果相同则继续进行连接,否则会发出一个致命错误中断连接,反之亦然;
 
(5)握手协议中,除了Hello Request消息外,所有选中的消息必须严格按照图3的顺序发送,否则会产生一个致命错误。
 

 
图4 TLS1.2密钥派生
 
6. TLS协议安全

TLS的安全主要集中在:
 
(1)强制使用较安全的TLS协议,如TLS1.2和TLS1.3;
 
(2) 对证书的要求,如在证书的扩展项中,至少提供一个CRL文件或OCSP responder的URL;当实现了OCSP协议时,建议使用OCSP stapling;当证书的撤回信息无法获取时,须断开连接;当证书被重新发布后,必须生成新的密钥;
 
(3)选择比较安全的TLS扩展,禁止使用不安全的扩展,推荐的扩展(extension)如Extended Master Secret、Signature Algorithms、Certificate Status Request等;禁止使用的扩展如server_certificate_type、Raw Public Keys;
 
(4)对于外部连接使用双方认证;
 
(5)对加密套件的要求,尽可能选择AEAD和前向安全的加密套件;
 
(6) 对已知的漏洞进行检测。
 
7.TLS协议面临的威胁
 
围绕TLS的威胁主要从协议实现、协议配置、证书、TLS运行环境。由于TLS基于TCP/IP协议栈,自然而然的也面临TCP/IP协议栈不可避免地问题,如TCP的各类Flood威胁。同时HTTPS的广泛使用,TLS的威胁很多都与web安全相关。
 
图5是github上一大神列举出的SSL协议模型:
 

图5 SSL威胁模型
 
那么如何评估自己的TLS已经达到一个安全状态呢?个人理解可以分为三部走:
 
(1)检查TLS配置合理;这里基于TLS的最佳实践,使用testssl.py和sslyze对TLS协议状态进行检测;
 
(2)检查TLS没有已知的漏洞;这里使用testssl.py检查对协议栈漏洞进行评估;
 
(3)挖掘TLS漏洞;这里自由发挥,可以对TLS的状态机、TLS的API进行模糊测试等;图6显示的便是很早之前对openssl 1.0.1g的状态机进行fuzz的结果。我们希望能够从中找出可以利用的攻击状态路径图。
 

图6 Openssl状态机模糊测试
 
8. 总结 

TLS是TCP/IP与密码学融合的产物,强大的密码学保证了运行在TLS上的DoIP、HTTP等数据的机密性、完整性。但TLS不是万能的,有了TLS也不能保证业务场景万无一失。作为网络安全从业者,我们需要在保证TLS的配置是最佳的前提下,不断挖掘TLS协议栈的漏洞,为下一次的HeartBleed做准备。

来源:汽车信息安全

 

Copyright © 2017-2024 河南中瀚安全技术有限公司 版权所有 豫ICP备18011434号-1 豫公网安备 41019702002746号