Total Pageviews

Showing posts with label tls/ssl. Show all posts
Showing posts with label tls/ssl. Show all posts

Wednesday, 22 January 2020

SSL v3.0 安全问题:POODLE漏洞实操

前言

各大浏览器、操作系统都屏蔽掉了SSLv2.0、SSLv3.0,原因是“不安全”,我们来分析SSL v3.0为什么不安全。

一、 POODLE简介

2014年9月Google的一份研究报告《This POODLE Bites: Exploiting The SSL 3.0 Fallback》指出,SSL存在安全漏洞CVE­-2014-3566,代号为POODLE(Padding Oracle On Downgraded Legacy Encryption,基于降级旧加密协议的填充提示),该漏洞可以使得攻击者获取到一段明文数据,比如HTTP的cookie,且除了完全禁用SSL,或者利用TLS_FALLBACK_SCSV字段禁止协议降级到SSL,没有其他更好的手段可以防御。

二、Padding Oracle 攻击原理

Padding Oracle是Web程序渗透的经典攻击方式,由Juliano Rizzo和Thai Duong于2010年《Practical Padding Oracle Attacks》提出,该攻击利用CBC(Cipher-block chaining,密码块链接模式)加密模式中的填充漏洞给出的提示信息逐步推导出明文数据。

相关帖子:

SSL/TLS发展历史和SSLv3.0协议详解

一、SSL/TLS发展历史


现在最安全的证书协议:tls1.3
SSL(Secure Socket Layer,安全套接层)v1.0最早于由网景公司(Netscape,以浏览器闻名)在1994年提出,该方案第一次解决了安全传输的问题。1995年公开发布了SSLv2.0,该方案于2011年被弃用(RFC6176 - Prohibiting Secure Sockets Layer (SSL) Version 2.0)。1996年发布了SSLv3.0(2011年才补充的RFC文档:RFC 6101 - The Secure Sockets Layer (SSL) Protocol Version 3.0),被大规模应用,于2015年弃用(RFC7568 - Deprecating Secure Sockets Layer Version 3.0)。这之后经过几年发展,于1999年被IETF纳入标准化(RFC2246 - The TLS Protocol Version 1.0),改名叫TLS(Transport Layer Security Protocol,安全传输层协议),和SSLv3.0相比几乎没有做什么改动。2006年提出了TLS v1.1(RFC4346 - The Transport Layer Security (TLS) Protocol Version 1.1),修复了一些bug,支持更多参数。2008年提出了TLS v1.2(RFC5246 - The Transport Layer Security (TLS) Protocol Version 1.2)做了更多的扩展和算法改进,是目前(2019年)几乎所有新设备的标配。TLS v1.3在2014年已经提出,2016年开始草案制定,然而由于TLS v1.2的广泛应用,必须要考虑到支持v1.2的网络设备能够兼容v1.3,因此反复修改直到第28个草案才于2018年正式纳入标准(The Transport Layer Security (TLS) Protocol Version 1.3)。TLSv1.3改善了握手流程,减少了时延,并采用完全前向安全的密钥交换算法。

二、SSL/TLS现状

SSLv1.0~v3.0都已经不安全了,2015年SSLv3.0也被官方弃用,各大平台也都不推荐使用,像java从2015年1月20日开始JDK 8u31、JDK 7u75、JDK 6u91和更高版本将默认禁用SSLv3。TLSv1.0、TLSv1.1也都只是SSL的过渡版本,TLSv1.2是目前大多数终端、平台使用的标准协议。TLSv1.3是正在大力推广的协议,例如阿里云的服务器、又拍云的CDN、Chome和FireFox浏览器都已经支持TLSv1.3了。
协议使用情况 
 SSLv3.0以下 有安全问题,且已被废弃,不建议使用 
 TLSv1.0/v1.1 过渡版本,不建议使用
 TLSv1.2 目前绝大多数都在使用,不知道选什么就选这个版本
 TLSv1.3 最新的更快更安全的协议,如果有条件建议一步到位

SSL/TLS由于使用了加密算法,非常消耗CPU资源,因此应该尽可能将SSL在LB(负载均衡,Load Balance)层终结掉。终结的意思是负载均衡器对外提供SSL连接,对内提供TCP连接,把SSL剥离掉。这样传输更快,且后端服务不需要消耗CPU资源处理SSL了(后端服务一般都是VPC的,肯定安全)。常见的开源负载均衡器HAProxy、开源反向代理Nginx、收费负载均衡器AWS ELB等都是可以终结的。

三、SSLv3.0协议

3.1 SSLv3.0简介


3.1.1 分层
SSLv3.0工作在经典TCP/IP五层中传输层和应用层之间,主要分为2层:
  • 握手协议层(Handshake Protocol Layer):负责SSL的逻辑协议
  • 记录层(Record Layer):负责SSL底层数据传输,为握手协议层提供支持
3.1.2 传输层协议选择
传输层一般都是TCP,需要可靠的传输层协议,所以UDP不应该被用来承载SSL。原话在RFC第一章Introduce:At the lowest level, layered on top of some reliable transport protocol (e.g., TCP [RFC0793])。
3.1.3 SSL协议
握手协议层有三个协议,分别是握手协议(Handshake Protocol)、更换加密规约协议(Change Cipher Spec Protocol)、告警协议(Alert Protocol)。
我们这里把更多的注意力放到握手协议层的握手协议上面。

3.2 SSLv3.0状态数据

SSLv3.0有两类状态数据。
第一类是会话状态(Session State),由握手协议创建,定义了一组可以被多个连接共用的密码安全参数,包括:
  • 会话ID( session identifier)服务器选择的标记一个活动的或可恢复会话的字符序列
  • 对等证书(peer certificate) x509.v3,可为空
  • 压缩算法(compress method):加密前压缩数据的算法
  • 密码规约(cipher spec):指定批量数据加密算法(如null、DES)和一个MAC算法(MD5、SHA),定义一些属性例如哈希大小(hash_size)
  • 主密钥(master secret):服务端和客户端共享的48字节密钥
  • 可恢复标记(is resumable):标记一个session的连接是否可恢复
第二类是连接状态(Connection State),记录了每个连接具体的一些密钥,包括:
  • 服务端和客户端随机数(server and client random):每次连接客户端和服务端选择的字符序列
  • 服务端写操作消息验证码密钥(server write MAC secret):用于服务端写数据时MAC操作的密钥
  • 客户端写操作消息验证码密钥(client write MAC secret):用于客户端写数据时MAC操作的密钥
  • 服务端写操作密钥(server write key):用于服务端数据加密和客户端解密的批量密码密钥
  • 客户端写操作密钥(client write key):用于客户端数据加密和服务端解密的批量密码密钥
  • 初始化向量(initialization vectors):当使用密码分组链接模式Cipher Block Chaining (CBC)时,为每个密钥维护初始化向量,这个字段会首先由SSL握手协议初始化,此后每个记录的最终密文块(ciphertext block)会被保留以用于后续记录
  • 序列号(sequence numbers):每一方都会为每个连接发送和接收消息维护一个序列号,当一方发送或接收修改密码规约cipher spec消息时,会将相应的序列号重置为0,序列号是无符号长整型uint64的,不能超过2^64-1。

3.3 SSLv3.0 握手过程


在完成传输层握手后,进入SSL Handshake阶段:
(1)客户端发送Client Hello Message,表明自己要使用的SSL版本、以及相应参数。
  • client_version:SSL版本。客户端会从高到低去尝试填入自己支持的SSL版本,例如这里就是SSLv3.0。
  • random:客户端随机数。客户端的随机字符序列,用于后续协商密钥。
  • session_id:本次会话ID。用于后面恢复会话。如果没有会话ID,则这里可以为空。
  • cipher_suites:支持的加密套件列表。根据客户端想要使用的且自己支持的加密套件由高到低排序。
  • compression_methods:压缩算法列表。根据客户端想要使用的且自己支持的压缩算法由高到低排序。可以为null,表示不要压缩。
一个加密套件包括四个部分(可参看RFC Appendix C. CipherSuite Definitions):
  • Is Exportable:是否可以导出
  • Key Exchange:密钥交换算法。用于密钥协商。
  • Cipher:对称加密算法。用于信息加密。
  • Hash:MAC的计算方法。用于完整性检验。
例如一个典型的加密套件SSL_RSA_WITH_RC4_128_SHA的含义为:
参数名 参数值 
 Is Exportable false
 Key Exchange RSA
 Cipher RC4_128
  Hash SHA
(2)服务端反馈信息,并可选地要求验证客户端身份。
这些消息是通过一次传输就传递完的,不分开。
【Server Hello】反馈信息
  • server_version:服务器支持的SSL版本。例如这里就是SSLv3.0。
  • random:服务器随机数。服务器端的随机字符序列,用于后续协商密钥。
  • session_id:本次会话ID。如果服务器找到了客户端传过来的session_id会话,并且可以恢复会话,那么这里会填入和Client Hello相同的session_id;否则这里将填入新session_id
  • cipher_suite:密钥套件。服务器支持的,且是从客户端给的列表中选的密钥套件。
  • compression_method:压缩算法。服务器支持的,且是从客户端给的列表中选的压缩算法。
【Certificate*】服务器证书
和所选密钥套件中密钥交换算法(Key Exchange)匹配的,用于客户端验证服务器身份和交换密钥的X.509证书。
【Server Key Exchange*】服务器密钥交换信息
如果服务器没有证书,或者服务器的证书仅用来签名(如DSS证书、签名RSA证书),或者使用的是FORTEZZA KEA密钥交换算法(现在已经不用了,不需要去了解),那么就需要发送这条消息。
【Certificate Request *】证书请求
要求客户端也发送它的证书,让服务端校验客户端的身份。
【Server Hello Done】服务器Hello阶段结束信息  
一条简单的表明状态的空消息。
(3)客户端校验服务端身份
【校验服务器身份】
客户端会校验服务器发过来的证书的合法性,包括:
  • 证书链的可信性
  • 证书是否被吊销
  • 证书是否处于有效期
  • 证书的域名是否和当前访问域名匹配
如果发现证书不合法,客户端可以发起告警信息。
(4)客户端回应服务端
【Certificate*】客户端证书
如果服务器发送了“Certificate Request”,要求校验客户端身份,那么客户端需要回应自己的证书。如果客户端没有合适的证书,直接抛出告警信息让服务端处理(服务端的处理方式通常就是断开TCP连接)。和所选密钥套件中密钥交换算法(Key Exchange)匹配的,用于服务器验证客户端身份的X.509证书。
【Client Key Exchange*】客户端密钥交换信息  
对于不同的密钥交换算法,密钥交换信息格式也不同:
密钥交换算法 密钥交换信息 
 RSA EncryptedPreMasterSecret
 Diffie-Hellman ClientDiffieHellmanPublic
 Fortezza Kea FortezzaKeys

通常我们都会用RSA,而RSA的密钥交换信息就是加密的预主密钥(Encrypted Pre-Master Secret)。服务端会生成48字节的预主密钥,用服务器传过来的公钥证书加密该预主密钥。
【Certificate Verify*】客户端证书校验信息
用于提供客户端证书的显示校验信息,仅在具有签名功能的客户端证书(也就是除包含固定diffie-hellman参数的证书外的所有证书)之后发送。它是采用客户端的私钥加密的一段基于已经协商的通信信息得到的数据,服务器可以用公钥解密验证。
【Change Cipher Spec】更换加密规约
用于提示服务端这条连接以后都使用当前协商好的加密方式以及主密钥。
【Finish(Encrypted Handshake Message)】完成信息
当所有操作完成后,发送Finish信息。Finish信息包含了Handshake信息、主密钥的哈希散列(如SHA、MD5)数据,用于验证身份校验和密钥交换过程都成功了。Finish消息不要求收到回包,发送之后可以立刻进行加密应用数据传输。
(5)服务端回应客户端
服务端同样地发送Change Cipher Spec、Finish(Encrypted Handshake Message)消息,然后开始数据传输。

3.4 SSL的认证方式

SSL的认证方式有3种:
  • 单向认证。客户端认证服务器。
  • 双向认证。客户端认证服务器、服务器认证客户端。
  • 匿名认证。不做任何身份校验。SSL反对使用该模式。

单向认证和双向认证相比,只是不需要客户端上传证书,其他没有区别。

3.5 复用会话


正常的SSL连接建立需要2个RTT(Round-Trip Time,往返时延),SSL协议规定可以复用会话,将其握手缩短到1个RTT。
如果服务端找到Client Hello中的session_id,那么直接复用该会话信息,发送的ServerHello中的session_id与ClientHello相同,并直接进入ChangeCipherSpec末尾阶段,完成握手。要注意,会话建立的连接会采用ClienHello中客户端随机数、ServerHello中客户端随机数生成的新的通信密钥,而不是上一个连接的旧密钥。
session_id不利于分布式,后面TLS在Client Hello的extension增加了session_ticket字段,类似于Web服务器Session和JWT Token的关系,具体情况具体使用。

3.6 SSL密钥计算

SSL定义了预备状态(pending state)和当前状态(current operating state)。
  • 预备状态:包含本次握手过程中协商的各种算法和密钥
  • 当前状态:包含记录层正在使用的各种算法和密钥
并且,客户端和服务器分别维护各自的读状态和写状态。
  • 读状态:包含解密算法(对端加密算法的解密算法)、解压缩算法(对端压缩算法的解压缩算法)、MAC验证算法(对端MAC生成算法的验证算法),解密密钥(对端写密钥的解密密钥,一般都是对等密钥)
  • 写状态:包含加密算法(己端加密算法)、压缩算法(己端压缩算法)、MAC生成算法(己端MAC生成算法),加密密钥(己端写密钥)
当客户端或服务器收到Change Cipher Spec消息后,会将预备读状态复制到当前读状态;
当客户端或服务器发送Change Cipher Spec消息后,会将预备写状态复制到当前写状态。

不同的握手密钥生成方式不同,这里以RSA为例(这里不用标准的变量名,而用带含义的,便于区别):
(1)客户端通过Client Hello发送客户端随机数Random_C,服务器也保存一份。
(2)服务器通过Server Hello发送服务器随机数Random_S和公钥证书public key,客户端也保存一份。
(3)客户端校验完服务器公钥证书后,将这个公钥同时用作加密用途。在Client Key Exchange阶段,利用公钥加密生成的预主密钥Pre-Master Secret。
(4)服务器收到预主密钥后,用自己的私钥解开得到明文预主密钥。
(5)客户端和服务器此时都有Random_C、Random_S、Pre-Master Secret,利用密钥导出函数KDF生成主密钥Master Secret。KDF一般是哈希函数,比如:
  1. Master Secret = MD5(Pre-Master Secret + SHA('A' + Pre-Master Secret + Random_C + Random_S))
  2. + MD5(Pre-Master Secret + SHA('BB'+ Pre-Master Secret + Random_C + Random_S))
  3. + MD5(Pre-Master Secret + SHA('CCC'+ Pre-Master Secret + Random_C + Random_S))
(6)再利用Master Secret生成密钥块keyblock,截取出6个参数,生成通信密钥。
  1. Keyblock = MD5(Master Secret + SHA('A' + Pre-Master Secret + Random_C + Random_S))
  2. + MD5(Master Secret + SHA('BB'+ Pre-Master Secret + Random_C + Random_S))
  3. + MD5(Master Secret + SHA('CCC'+ Pre-Master Secret + Random_C + Random_S))
  4. + ……
分别截取出客户端写MAC密钥、服务器写MAC密钥、客户端写密钥、服务器写密钥、客户端IV、服务端IV(如果用了CBC的话)。
(7)发出ChangeCipherSpec消息,将这些密钥拷贝到记录层,用于读密钥、写密钥。例如,客户端写、服务器读用客户端写密钥;服务器写、客户端读用服务器写密钥,加密方式是对称加密。

配置域名bwb.com,以及对应的证书、私钥,配置SSL协议固定为SSLv3:
  1. server{
  2. listen 443;
  3. server_name bwb.com;
  4. ssl on;
  5. ssl_certificate /path/to/bwb.crt;
  6. ssl_certificate_key /path/to/bwb.key;
  7. ssl_protocols SSLv3;
  8.  
  9. location / {
  10. root html;
  11. index index.html;
  12. }
  13. }

参考资料

1、《信息安全系统工程SSL和OpenSSL》:似乎是信安的课程PPT,思路清晰
2、《RFC 6101 SSL v3.0》:官方英文文档

证书链-Digital Certificates

基础知识

在介绍证书链之前,需要首先了解一下非对称加密以及电子证书相关的基础概念。关于这部分,我也一直有些困惑,直到看了阮一峰老师的博客,才对证书有个比较清晰的认知。参考:http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.html
看完阮老师的博客,一定对道格冒充鲍勃,然后将自己的公钥发送给苏珊那部分很困惑。后面就对这部分知识展开说一下。

证书 & CA

证书

首先,我们看看在wikipedia上对证书的定义,In cryptography, a public key certificate (also known as a digital certificate or identity certificate) is an electronic document used to prove ownership of a public key.。可以这么说,证书是用来认证公钥持有者的身份的电子文档,防止第三方进行冒充。一个证书中包含了公钥、持有者信息、证明证书内容有效的签名以及证书有效期,还有一些其他额外信息。

CA

我们用证书来认证公钥持有者的身份,那证书是怎么来的呢?又该怎么认证证书呢?这涉及到一个称之为PKI(Public key certificate)的规范体系,包含了数字证书,公钥管理以及验证等技术,详细可以参考:https://en.wikipedia.org/wiki/Public_key_certificate ,我们这里只是简单介绍一下概念。在阮老师的文章中,提到证书要由证书中心(Certificate authority,简称CA)签发的,同样参考Wikipedia上的概念,In cryptography, a certificate authority or certification authority (CA) is an entity that issues digital certificates. (https://en.wikipedia.org/wiki/Certificate_authority) ,简单来说,CA就是签发电子证书的实体。

Signing & Verification

证书的签发(Signing)和认证(Verification)的过程:

这两个过程也是基于公钥与私钥的,签发和认证的过程跟传输信息过程中的加密解密过程非常类似。签名密文(Signature)是一个重要凭证,Signature与签发人的公钥一同传输,可以避免中间人在获取证书时对证书内容的篡改。参考:http://blog.torchz.net/security/2014/12/23/security-ca-chain-of-trust.html
签发证书的步骤
  1. Signing阶段,首先撰写证书的元信息:签发人(Issuer)、地址、签发时间、过期失效等;当然,这些信息中还包含证书持有者(owner)的基本信息,例如owner的DN(DNS Name,即证书生效的域名),owner的公钥等基本信息。
  2. 通过通用的Hash算法将信息摘要提取出来;
  3. Hash摘要通过Issuer(CA)私钥进行非对称加密,生成一个签名密文;
  4. 将签名密文attach到文件证书上,使之变成一个签名过的证书。
验证证书的步骤
  1. Verification阶段,浏览器获得之前签发的证书;
  2. 将其解压后分别获得“元数据”和“签名密文”;
  3. 将同样的Hash算法应用到“元数据”获取摘要;
  4. 将密文通过Issuer(CA)的公钥(非对称算法,私钥加密,公钥解密)解密获得同样的摘要值。
  5. 比对两个摘要,如果匹配,则说明这个证书是被CA验证过合法证书,里面的公钥等信息是可信的。
在Verification阶段,解密Signature获得摘要需要通过签发者(Issuer)的公钥,又该如何获得这个公钥,同时确保这个公钥是有效的呢?就是下面的证书链的内容

证书链

实例

在Chrome上任意打开一个支持HTTPS的网站,例如 https://www.baidu.com/ ,我们会发现在地址栏的左侧有个绿色的小锁,点击这个小锁,然后就可以查看这个网站的证书信息。

我们继续探究baidu使用的HTTPS证书,除了HTTPS使用的 baidu.com 证书,向上还有两级证书,证书有3类:
  1. end-user :baidu.com 包含用来加密传输数据的公钥的证书,是HTTPS中使用的证书
  2. intermediates:CA用来认证公钥持有者身份的证书,即确认HTTPS使用的end-user证书是属于baidu.com的证书。这类intermediates证书甚至可以有很多级。
  3. root:用来认证intermediates证书是合法证书的证书。
简单来说,end-user证书上面几级证书都是为了保证end-user证书未被篡改,保证是CA签发的合法证书,进而保证end-user证书中的公钥未被篡改。

证书链

CA组织

除了end-user之外,证书被分为root Certificates和intermediates Certificates。相应地,CA也分了两种类型:root CAs 和 intermediates CAs。首先,CA的组织结构是一个树结构,一个root CAs下面包含多个intermediates CAs,而intermediates又可以包含多个intermediates CAs。root CAs 和 intermediates CAs都可以颁发证书给用户,颁发的证书分别是root Certificates和intermediates Certificates,最终用户用来认证公钥的证书则被称为end-user Certificates。

end-user certificates & intermediates certificates

我们使用end-user certificates来确保加密传输数据的公钥(public key)不被篡改,而又如何确保end-user certificates的合法性呢?这个认证过程跟公钥的认证过程类似,首先获取颁布end-user certificates的CA的证书,然后验证end-user certificates的signature。一般来说,root CAs不会直接颁布end-user certificates的,而是授权给多个二级CA,而二级CA又可以授权给多个三级CA,这些中间的CA就是intermediates CAs,它们才会颁布end-user certificates。
但是intermediates certificates的可靠性又如何保证呢?这就是涉及到证书链,Certificate Chain ,链式向上验证证书,直到Root Certificates,如下图:

root certificates

那Root Certificates又是如何来的呢?根据 https://support.dnsimple.com/articles/what-is-ssl-certificate-chain/ 这篇文章的说法,除了可以下载安装之外,device(例如浏览器,操作系统)都会内置一些root certificates,称之为trusted root certificates,https://support.apple.com/en-us/HT202858 ,在Apple的官网上可以看到这个列表,有各个操作版本直接内置的Root Certificates。
最后一个问题,为什么需要证书链这么麻烦的流程?Root CA为什么不直接版本证书,而是要搞那么多中间层级呢?找了一下,godaddy官方给了一个答案,为了确保root certificates的绝对安全性,https://sg.godaddy.com/en/help/what-is-an-intermediate-certificate-868 ,将根证书隔离地越严格越好。

其他

了解了这个证书体系之后,才明白为什么百度/google这种公司也需要向第三方购买签名证书了,自签root证书推广起来非常困难,这也导致目前的证书市场基本上被 Symantec(VeriSign/GeoTrust) / Comodo / GoDaddy 垄断。百度使用的是Versign,google使用的是GeoTrust。目前HTTPS的推广已经不可避免,也已经有一些公益组织开始提供免费、自动化、开放的证书签发服务,例如:Let's Encrypt 。详细使用可以参考奇舞周刊的这篇文章,Let's Encrypt,免费好用的 HTTPS 证书
最后,对于Mac中各种各样的证书,可以通过Keychain Access来管理查看。在Keychain Access对某个证书执行Evaluate,就能得到证书链信息.

参考资料

4、《DV型和OV型证书的区别》
--------------------------

CA & chain of trust

有个争议点,主要是针对CA究竟能不能被hack,在这里解释一下CA证书真正的签发与验证原理。
如下图,签发与认证 :CA sign and verify
###签发证书的步骤:
  1. Signing阶段,首先撰写证书的元信息:签发人、地址、签发时间、过期失效等等;
  2. 通过通用的hash算法将信息摘要提取出来;
  3. Hash摘要通过签发者的私钥进行非对称加密,生成一个签名密文;
  4. 将签名密文attach到文件证书上,使之变成一个签名过的证书。
###验证证书的步骤:
  1. Verification阶段,浏览器获得之前签发的证书;
  2. 将其解压后分别获得“元数据”和“签名密文”;
  3. 将同样的Hash算法应用到“元数据”获取摘要;
  4. 将密文通过公钥(非对称算法,私钥加密,公钥解密)解密获得同样的摘要值。
在这里的签名密文是一个重要凭证,Signature与签发人的公钥一同传输,可以避免中间人在获取证书时对证书内容的篡改。
通过CA,可以保证server提供的公钥(public key)不被proxy篡改,否则签发“元信息”不满足信任链(Chain of trust),会被浏览器识别为“不安全”的。
有关信任链的验证流程,可以参考下图: chain of trust
利用这个CA提供的公钥,可以为TLS的握手提供第一次交换密文随机数,之后就可以使用对称加密通信了。