SSL / TLS如何工作?

SSL如何工作?我刚刚意识到我们实际上并没有确定的答案,这是值得报道的。

我希望看到详细信息:

  • 协议的高级描述。
  • 密钥交换如何工作。
  • 如何执行真实性,完整性和保密性。
  • 拥有CA的目的是什么,以及他们如何颁发证书。
  • 涉及任何重要技术和标准(例如PKCS)的细节。

一般

SSL(及其后继者,TLS)是一种直接在TCP之上运行的协议(尽管也有基于数据报协议的实现,如UDP)。这样,更高层(例如HTTP)上的协议可以保持不变,同时仍然提供安全连接。在SSL层下面,HTTP与HTTPS相同。

正确使用SSL / TLS时,攻击者可以在电缆上看到您连接的是哪个IP和端口,大致发送了多少数据以及使用了哪种加密和压缩。他也可以终止连接,但双方都知道连接被第三方中断。

在典型的使用中,攻击者也将能够找出你连接的主机名(但不是URL的其余部分):虽然HTTPS本身不公开主机名,但你的浏览器通常需要创建一个DNS首先请求找出发送请求的IP地址。

协议的高级描述

建立TCP连接后,SSL握手由客户端启动。客户端(可以是浏览器以及任何其他程序,例如Windows Update或PuTTY)会发送多种规格:

  • 其中SSL的版本/ TLS正在运行,
  • 它想要使用什么密码套件,以及
  • 它想要使用什么压缩方法

服务器检查它们支持的最高SSL / TLS版本,从客户端的一个选项(如果它支持一个选项)中挑选一个密码组,并且可以选择一种压缩方法。

在此基本设置完成后,服务器发送其证书。该证书必须由客户自己或客户信任的一方信任。例如,如果客户信任GeoTrust,则客户可以信任来自Google.com的证书,因为GeoTrust以加密方式签署了Google的证书。

验证了证书并确定这台服务器真的是他自称的人(而不是中间的人),交换了一个密钥。这可以是一个公钥,一个“PreMasterSecret”或根本就没有,取决于选择的密码套件。现在服务器和客户端都可以计算对称加密 的密钥,而PKE?。客户端告诉服务器,从现在开始,所有通信都将被加密,并向服务器发送加密和认证消息。

服务器验证MAC(用于身份验证)是否正确,并且消息可以正确解密。然后它返回一条消息,客户端也会对其进行验证。

握手现在已经完成,两台主机可以安全通信。有关更多信息,请参阅technet.microsoft.com/en-us/library/cc785811en.wikipedia.org/wiki/Secure_Sockets_Layer

要关闭连接,请使用close_notify’alert’。如果攻击者试图通过完成TCP连接(注入一个FIN数据包)来终止连接,则双方都会知道连接不正确终止。这个连接不能被破坏,只是被打断了。

一些更多细节

为什么您可以信任GeoTrust来信任Google.com?

一个网站想要安全地与你沟通。为了证明它的身份并确保它不是攻击者,你必须拥有服务器的公钥。但是,您几乎不能存储全球所有网站上的所有密钥,数据库将会非常庞大​​,并且更新必须每小时运行一次!

解决方案是证书颁发机构,简称CA。当您安装操作系统或浏览器时,可能会附带一个可信CA列表。这个列表可以随意修改; 您可以删除不信任的人,添加其他人,甚至可以创建自己的CA(尽管您将是唯一一个信任此CA的人,因此它对公共网站没有多大用处)。在此CA列表中,CA的公钥也被存储。

当Google的服务器向您发送证书时,它也会提及它由GeoTrust签署。如果您信任GeoTrust,您可以验证(使用GeoTrust的公钥)GeoTrust确实签署了服务器的证书。要亲自签署证书,您需要只有GeoTrust才知道的私钥。这样攻击者不能自己签署证书,并且不正确地声称自己是Google.com。当证书被修改了一位时,该标志将不正确,客户端将拒绝它。

所以如果我知道公钥,服务器可以证明它的身份?

是。通常,公钥加密和私钥解密。使用服务器的公钥加密消息,发送消息,如果服务器可以重复回复原始消息,它只是证明它获得私钥而不泄露密钥。

这就是为什么能够信任公钥非常重要的原因:任何人都可以生成私钥/公钥对,也是攻击者。你不想最终使用攻击者的公钥!

如果您信任的某个CA遭到入侵,攻击者可以使用被盗私钥为他们喜欢的任何网站签发证书。当攻击者可以向您的客户端发送伪造的证书时,他自己用您信任的CA的私钥签名,您的客户端不知道公钥是伪造的,并且使用被盗私钥签名。

但CA可以让我相信他们想要的任何服务器!

是的,那就是信任的来源。你必须相信CA不会根据自己的意愿制作证书。当微软,苹果和Mozilla等组织信任CA时,CA必须进行审计; 另一个组织会定期检查它们以确保所有内容都按照规则运行。

只有在注册人可以证明他们拥有颁发证书的域名的情况下,才会颁发证书。

什么是MAC用于消息认证?

每条消息都使用所谓的消息认证码(简称MAC)进行签名。如果我们同意密钥和哈希密码,则可以验证我的消息来自我,并且我可以验证您的消息来自您。

例如,使用“正确的马电池钉”键和“示例”消息,我可以计算MAC“58393”。当我用MAC发送这条消息给你(你已经知道密钥)时,你可以执行相同的计算并将计算出的MAC与我发送的MAC进行匹配。

攻击者可以修改消息,但不知道密钥。他无法计算正确的MAC,并且您会知道该消息不是真实的。

通过在计算MAC时包含序列号,可以消除重播攻击SSL执行此操作。

你说客户端发送了一个密钥,然后用它来建立对称加密。什么阻止攻击者使用它?

服务器的公钥确实。既然我们已经证实公钥真的属于服务器而不是其他人,我们可以使用公钥对密钥进行加密。当服务器收到这个消息时,他可以用私钥解密。当其他人收到它时,他们不能解密它。

这也是密钥大小很重要的原因:公钥和私钥越大,破解客户端发送到服务器的密钥就越难。

如何破解SSL

总结

  • 尝试用户是否忽略证书警告;
  • 应用程序可能会从未加密的通道(例如http)加载数据,这些数据可能会被篡改;
  • 提交给HTTPS的未受保护的登录页面可能会被修改,以便提交给HTTP;
  • 未打补丁的应用程序可能因BEAST和CRIME等攻击而受到攻击;
  • 诉诸其他方法,如物理攻击;
  • 利用消息长度和形成消息所花费的时间旁道 ;
  • 等待量子攻击

另请参阅:由Ivan Ristic (png)提供的针对SSL的许多攻击向量的方案

详细:

没有简单而直接的方法; 如果正确完成,SSL是安全的。如果用户忽略证书警告,攻击者可以尝试,这会立即破坏安全。当用户这样做时,攻击者不需要来自CA的私钥来伪造证书,他只需发送他自己的证书。

另一种方法是通过应用程序(服务器端或客户端)中的缺陷。一个简单的例子就是在网站上:如果网站使用的某个资源(如图像或脚本)通过HTTP加载,则不再保证机密性。即使浏览器在从安全页面(源代码)请求非安全资源时,也不会发送HTTP Referer头),窃听流量的人仍然有可能猜测你访问的地点; 例如,如果他们知道图像X,Y和Z在一个页面上使用,他们可能会猜测当他们看到您的浏览器一次请求这三个图像时,您正在访问该页面。另外,当加载Javascript时,整个页面可能会受到影响。攻击者可以在页面上执行任何脚本,例如修改银行交易的目标。

发生这种情况时(通过HTTP加载资源),浏览器会发出混合内容警告:ChromeFirefoxInternet Explorer 9

HTTP的另一个诀窍是登录页面不安全时,它会提交到https页面。“很好,”开发者可能会想,“现在我节省了服务器负载,密码仍然被加密发送!” 问题是sslstrip,一种修改不安全登录页面的工具,以便它在某处提交,以便攻击者可以读取它。

过去几年中也发生过各种攻击,例如TLS重新协商漏洞sslsniffBEAST,以及最近的CRIME。尽管所有常见的浏览器都可以抵御所有这些攻击,但如果您运行的是最新浏览器,则这些漏洞无风险。

最后但并非最不重要的是,您可以使用其他方法获取SSL拒绝您获取的信息。如果您已经可以看到并篡改用户的连接,那么使用键盘记录器替换他/她的.exe下载中的一个可能并不难,或者仅仅是为了实际攻击该用户。密码学可能相当安全,但人类和人为错误仍然是一个薄弱的因素。根据Verizon的这篇文章,10%的数据泄露涉及物理攻击(请参阅第3页),所以这当然值得注意。


由于SSL的一般概念已经涵盖到其他一些问题中(例如这个那一个),这次我会详细介绍。细节很重要。这个答案会有些冗长。

历史

SSL是一个有着悠久历史和多个版本的协议。第一个原型来自Netscape,当时他们正在开发他们的旗舰浏览器Netscape Navigator的第一个版本(该浏览器在浏览器战争早期杀死了Mosaic,尽管新竞争对手仍在肆虐)。版本1从未公开过,因此我们不知道它的样子。可以在那里阅读的草案中描述了SSL版本2 ; 它有一些弱点,其中一些非常严重,所以它被弃用,而较新的SSL / TLS实现不支持它(尽管默认情况下较旧版本被禁用)。除了作为偶然的参考,我不会再提到SSL版本2。

SSL版本3(我将称之为“SSLv3”)是一种增强型协议,目前仍然有效,并得到广泛支持。虽然Netscape Communications仍然是一个属性(或者现在拥有它的人),但该协议已经作为“历史RFC”(RFC 6101)发布。同时,该协议已经标准化,并以一个新名称来避免法律问题; 新名称是TLS

到目前为止,已经制作了三个TLS版本,每个都有其专用的RFC:TLS 1.0TLS 1.1TLS 1.2。它们在内部非常相似,并且使用SSLv3,以至于一个实现可以轻松支持SSLv3,并且所有三个TLS版本至少有95%的代码是通用的。仍然在内部,所有版本都由具有major.minor的版本号指定格式; 那么SSLv3是3.0,而TLS版本分别是3.1,3.2和3.3。因此,难怪TLS 1.0有时被称为SSL 3.1(也是不正确的)。SSL 3.0和TLS 1.0只有一些微小的细节。TLS 1.1和1.2还没有得到广泛支持,但由于可能的弱点(见下文,对于“BEAST攻击”),有这种动力。“无处不在”支持SSLv3和TLS 1.0(即使IE 6.0也了解它们)。

上下文

SSL旨在为任意数据提供安全的双向隧道。考虑TCP,这是众所周知的通过Internet发送数据的协议。TCP通过IP“数据包”工作并为字节提供双向隧道; 它适用于每个字节值并将它们发送到可同时操作的两个流中。TCP处理将数据拆分为数据包,确认数据,将数据重新组合成正确顺序,同时删除重复数据包并重新发送丢失数据包的艰巨工作。从使用TCP的应用程序的角度来看,只有两个流,而数据包是不可见的; 特别是这些数据流不会被分解为“消息”(如果应用程序希望拥有消息,则需要采用自己的编码规则, 一样)。

在出现“事故”时,TCP是可靠的,即由于片状硬件造成的传输错误,网络拥塞,智能手机走出某个基站的范围以及其他非恶意事件。然而,有一些访问传输介质的恶意个人(“攻击者”)可能会读取所有传输的数据和/或故意改变它,而TCP不能防止这种情况发生。因此SSL。

SSL 假定它通过类似TCP的协议工作,该协议提供可靠的流; SSL不会实现丢失数据包的重发以及类似的事情。攻击者应该有权以不可避免的方式完全中断通信(例如,他可以切断电缆),因此SSL的工作是:

  • 检测更改(攻击者不能无声地更改数据);
  • 确保数据机密性(攻击者不能获得交换数据的知识)。

SSL实现这些目标的程度很大(但不是绝对的)。

记录

SSL是分层的,底层是记录协议。无论在SSL隧道中发送的数据是否被分割成记录。在线路上(底层的TCP套接字或TCP类媒体),一条记录如下所示:

HH V1:V2 L1:L2 数据

哪里:

  • HH是指示记录中数据类型的单个字节。定义了四种类型:change_cipher_spec(20),alert(21),handshake(22)和application_data(23)。
  • V1:V2是两个字节以上的协议版本。对于当前定义的所有版本,V1值为0x03,而V2SSLv3的值为0x00,TLS 1.0的0x01,TLS 1.1的0x02和TLS 1.2的0x03。
  • L1:L2是以data字节为单位的长度(使用big-endian约定:长度为256 * L1 + L2)。总长度data不能超过18432字节,但实际上它甚至不能达到该值。

所以一个记录有一个5字节的标题,其后是最多18 kB的数据。这data是应用对称加密和完整性检查的地方。当记录发出时,发送方和接收方都应该同意当前应用哪些加密算法以及哪些密钥; 这个协议是通过握手协议获得的,在下一节中有描述。压缩(如果有的话)也适用于该点。

完整的细节,建立一个记录是这样的:

  • 最初,有一些字节要传输; 这些是应用程序数据或其他类型的字节。该有效负载最多由16384字节组成,但可能更少(长度为0的有效负载是合法的,但事实证明,Internet Explorer 6.0根本不喜欢这种情况)。
  • 然后使用目前商定的任何压缩算法压缩有效载荷。压缩是有状态的,因此可能取决于以前记录的内容。实际上,由于最近的CRIME攻击,压缩要么是“空白”(完全没有压缩),要么是“Deflate”(RFC 3749),后者目前有礼貌但坚定地显示了Web环境中的出口。压缩旨在缩短数据,但在一些不利的情况下(由于鸽子的原理),压缩必须稍微扩大一点。SSL允许扩展至多1024个字节。当然,null压缩永远不会扩展(但不会缩短); 如果执行情况良好,Deflate最多可扩展10个字节。
  • 然后保护压缩的有效载荷免受更改并加密。如果当前的加密和完整性算法是“空”,那么这一步是无操作的。否则,会追加一个MAC,然后进行一些填充(取决于加密算法),并将结果加密。这些步骤再次引发了一些扩展,SSL标准将其限制为1024个额外字节(与来自压缩步骤的最大扩展相结合,这使我们达到了18432个字节,我们必须添加5个字节的标题)。

该MAC是,通常情况下,HMAC与通常的散列函数(主要是MD5,SHA-1或SHA-256)(与SSLv3的一个,这是不是“真正的” HMAC但非常类似的东西,并给我们所知,与HMAC一样安全)。加密将使用CBC模式下的分组密码或RC4流密码。注意,理论上可以采用其他类型的模式或算法,例如结合加密和完整性检查的这些漂亮模式之一; 甚至有一些RFC。但实际上,部署的实现还不知道这些,所以他们做HMAC和CBC。最重要的是,MAC首先被计算并附加到数据上,并且结果被加密。这是MAC-then-encrypt,它实际上是不是一个好主意。MAC是通过(压缩)有效载荷和序列号的串联来计算的,因此勤劳的攻击者可能不会交换记录。

握手

所述握手是被记录协议内起到了协议。其目标是建立要用于记录的算法和密钥。它由消息组成。每个握手消息以4字节的头部开始,一个字节描述消息类型,然后3个字节的消息长度(大端规则)。随后的握手消息将与带有“handshake”类型标记的记录一起发送(每个记录的标题的第一个字节值为22)。

请注意层:握手消息,包含四个字节的标题,然后作为记录发送,每个记录有它自己的标题。此外,可以在同一条记录中发送多个握手消息,并且可以将多个记录分配给定的握手消息。从构建握手消息的模块的角度来看,“记录”只是可以发送字节的流; 它没有注意到该流的实际分割成记录。

全握手

最初,客户端和服务器“同意”没有MAC和零压缩的空加密。这意味着他们首先发送的记录将以明文形式发送并且不受保护。

第一个握手信息是a ClientHello。这是客户说明他们打算做SSL的意思的信息。请注意,“客户”是一个象征性的角色; 它意味着“先发言的派对”。恰巧在HTTPS上下文中,即TCP内部的HTTP内的所有三层都有“客户端”和“服务器”的概念,并且他们都同意(TCP客户端也是SSL客户端, HTTP客户端),但这有点巧合。

ClientHello消息包含:

  • 客户希望支持的最大协议版本;
  • “客户端随机”(32个字节,其中28个假设使用密码强数生成器生成);
  • “会话ID”(如果客户想要以简短握手方式恢复会话,请参见下文);
  • 客户端知道的“密码套件”列表,按客户端的偏好排序;
  • 客户端知道的压缩算法列表,由客户端首选项排序;
  • 一些可选的扩展。

密码套件是用于一组的加密算法的16比特的符号的标识符。例如,TLS_RSA_WITH_AES_128_CBC_SHA密码套件的值为0x002F,意思是“记录使用128位密钥的HMAC / SHA-1和AES加密,密钥交换通过使用服务器的RSA公钥加密随机密钥完成”。

服务器响应ClientHelloServerHello包含:

  • 客户端和服务器使用的协议版本;
  • “随机服务器”(32个字节,28个随机字节);
  • 此连接的会话ID;
  • 将使用的密码套件;
  • 将使用的压缩算法;
  • 可选地,一些扩展。

完整的握手如下所示:

  Client                                               Server

  ClientHello                  -------->
                                                  ServerHello
                                                 Certificate*
                                           ServerKeyExchange*
                                          CertificateRequest*
                               <--------      ServerHelloDone
  Certificate*
  ClientKeyExchange
  CertificateVerify*
  [ChangeCipherSpec]
  Finished                     -------->
                                           [ChangeCipherSpec]
                               <--------             Finished
  Application Data             <------->     Application Data

(这个模式已经从RFC中无耻地复制过来。)

我们看到ClientHelloServerHello。然后,服务器发送一些其他消息,这取决于密码套件和其他一些参数:

  • 证书:服务器的证书,其中包含其公钥。更多关于下面的内容。此消息几乎总是被发送,除非密码套件强制执行没有证书的握手。
  • ServerKeyExchange:密钥交换的一些额外值,如果证书中的内容不够用。特别是,“DHE”密码套件使用短暂的Diffie-Hellman密钥交换,它需要该消息。
  • CertificateRequest:一条消息,要求客户用自己的证书标识自己。此消息包含服务器用于验证客户机证书的信任锚(即“根证书”)的名称列表。
  • ServerHelloDone:标记消息(长度为零),表示服务器已完成,客户端现在应该说话。

客户必须回应:

  • 证书:客户端证书,如果服务器请求一个。版本之间有细微的差异(对于SSLv3,如果客户端没有证书,则必须忽略此消息;对于TLS 1.0+,在相同的情况下,它必须发送Certificate带有空证书列表的消息)。
  • ClientKeyExchange:实际密钥交换的客户端部分(例如用服务器RSA密钥加密的一些随机值)。
  • CertificateVerify:由客户端在以前的所有握手消息中计算的数字签名。该消息在服务器请求客户端证书并且客户端已编译时发送。这就是客户端向服务器证明它真正“拥有”在其发送的证书中编码的公钥的方式。

然后客户端发送一个ChangeCipherSpec消息,这不是一个握手消息:它有它自己的记录类型,所以它会以它自己的记录发送。它的内容纯粹是符号的(单个字节值为1)。此消息标志着客户端切换到新协商的密码套件和密钥的点。然后来自客户端的后续记录将被加密。

已完成的消息是计算在所有先前的握手消息加密校验(来自客户端和服务器)。由于它是在发布之后发布的ChangeCipherSpec,因此它还包含完整性检查和加密。当服务器收到该消息并验证其内容时,它会得到一个证明,证明它一直与同一个客户端交谈。此消息保护握手免受更改(攻击者无法修改握手消息并仍然Finished正确地获取消息)。

最后,服务器有自己的回应ChangeCipherSpecFinished。此时,握手完成,并且客户端和服务器可以交换应用程序数据(以加标签的形式加密的记录)。

记住:客户端建议但服务器选择。密码套件在服务器手中。有礼貌的服务器应该遵循客户的喜好(如果可能的话),但他们可以做其他事情,有些服务器可以做(例如作为保护BEAST的一部分)。

缩略握手

在完整握手中,服务器向客户端发送“会话ID”(即一串最多32字节)。稍后,客户端可以返回并发送相同的会话ID作为他的一部分ClientHello。这意味着客户端仍然记得先前握手的密码套件和密钥,并且希望重用这些参数。如果服务器记住密码套件和密钥,则它会在其中复制该特定会话标识ServerHello,然后遵循缩略握手

  Client                                                Server

  ClientHello                   -------->
                                                   ServerHello
                                            [ChangeCipherSpec]
                                <--------             Finished
  [ChangeCipherSpec]
  Finished                      -------->
  Application Data              <------->     Application Data

缩短的握手时间较短:消息较少,没有非对称加密业务,最重要的是缩短了延迟。网络浏览器和服务器做了很多。一个典型的Web浏览器将以完整的握手方式打开一个SSL连接,然后为同一服务器的所有其他连接执行缩略握手:并行打开的其他连接以及后续连接到同一服务器的连接。事实上,典型的Web服务器会在闲置15秒后关闭连接,但他们会记住会话(密码套件和密钥)很长时间(可能持续数小时甚至数天)。

密钥交换

有几种SSL可以使用的密钥交换算法。这由密码套件指定; 每种密钥交换算法都可以与某种服务器公钥一起工作。最常见的密钥交换算法是:

  • RSA:服务器的密钥是RSA类型的。客户端生成一个随机值(48个字节的“预主密钥”,其中46个是随机的),并使用服务器的公钥对其进行加密。没有ServerKeyExchange
  • DHE_RSA:服务器的密钥是RSA类型的密钥,但仅用于签名。实际的密钥交换使用Diffie-Hellman。服务器发送ServerKeyExchange包含DH参数(模数,生成器)和新生成的DH公钥的消息; 此外,服务器签署此消息。客户端将回复一条ClientKeyExchange消息,其中也包含一个新生成的DH公钥。卫生署产生「预主秘密」。
  • DHE_DSS:喜欢DHE_RSA,但服务器有一个DSS密钥(“DSS”也称为“DSA”)。DSS是仅签名算法。

较不常用的密钥交换算法包括:

  • DH:服务器密钥的类型是Diffie-Hellman(我们正在谈论一个包含DH密钥的证书)。当RSA专利仍然活跃时(这是在上个世纪期间),这曾经是以行政方式(美国联邦政府规定其使用)“流行”。尽管官僚推动,但它从未像RSA那样广泛部署。
  • DH_anon:像DHE套房一样,但没有来自服务器的签名。这是一个无证书密码套件。通过建设,它很容易受到中间人攻击,因此很少有人能够实现。
  • PSK预共享密钥密码套件。仅基于对称的密钥交换,建立在预先建立的共享密钥上。
  • SRP:是密码认证密钥交换协议的SRP协议的应用。客户端和服务器相互认证共享密钥,可以是低熵密码(而PSK需要高熵共享密钥)。非常漂亮。尚未得到广泛支持。
  • 一个短暂的RSA密钥:像DHE一个新生成的RSA密钥对一样。由于生成RSA密钥价格昂贵,因此这不是一种常用选项,并且仅被指定为符合2000年以前的美国密码学出口法规(即RSA密钥最多512位)的“导出”加密套件的一部分。现在没有人这样做。
  • 椭圆曲线DH*算法的变体。非常时尚。在未来应该会变得很普遍。

证书和认证

数字证书是不对称密钥的容器。它们旨在解决密钥分配问题。即,客户端想要使用服务器的公钥。攻击者会尝试让客户端使用攻击者的公钥。所以客户必须有办法确保它使用正确的密钥。

SSL应该使用X.509。这是证书的标准。每个证书都由证书颁发机构签署。这个想法是客户端固有地知道少数CA的公钥(这些是“信任锚”或“根证书”)。使用这些密钥,客户端可以验证由CA计算出来的签名,该签名是通过已颁发给服务器的证书进行的。该过程可以递归地扩展:CA可以为另一个CA(即标志)颁发证书包含其他CA名称和密钥的证书结构)。以根CA开始并以服务器证书结束的证书链,其间具有中间CA证书,每个证书相对于在先前证书中编码的公共密钥被签名,被认为是缺乏想象力的证书链

所以客户应该做到以下几点:

  • 获取以服务器证书结尾的证书链。Certificate准确地说,来自服务器的消息应该包含这样一个链。
  • 验证链,即验证所有签名和名称以及各种X.509位。另外,客户端应该检查链中所有证书的撤销状态,这是复杂而沉重的(Web浏览器现在已经这么做了,或多或少,但这是最近的发展)。
  • 验证预期的服务器名称是否确实写入服务器的证书中。因为客户端不仅要使用验证的公钥,还要使用特定服务器的公钥。有关如何在HTTPS上下文中完成此操作的详细信息,请参阅RFC 2818

X.509证书的认证模式经常受到批评,而不是真正的技术理由,而是出于政治经济原因。它将验证能力集中在少数玩家的手中,这些玩家并不一定善意,或者至少不总是胜任。其他系统的建议一经公布(如ConvergenceDNSSEC),但尚未获得广泛接受(尚未)。

对于基于证书的客户端身份验证,完全由服务器决定如何处理客户端证书(以及如何处理拒绝发送证书的客户端)。在Windows / IIS / Active Directory世界中,客户端证书应包含一个帐户名称作为“用户主体名称”(编码在证书的Subject Alt Name扩展名中); 服务器在其Active Directory服务器中查找它。

再次握手

由于握手只是一些使用当前加密/压缩规则作为记录发送的消息,因此理论上阻止SSL客户端和服务器在建立的SSL连接内进行第二次握手。事实上,它得到了支持,它在实践中发生了。

在任何时候,客户端或服务器都可以发起新的握手(服务器可以发送HelloRequest消息来触发它;客户端只是发送一个消息ClientHello)。典型的情况如下:

  • HTTPS服务器配置为侦听SSL请求。
  • 客户端连接并执行握手。
  • 一旦握手完成,客户端发送它的“应用数据”,它包含一个HTTP请求。在那时(并且仅在那一点),服务器学习目标路径。到目前为止,服务器不知道客户端希望访问的URL(服务器可能已通过服务器名称指示 SSL扩展来了解目标服务器名称,但这不包括路径)。
  • 在看到路径时,服务器可能知道这是针对其数据的一部分,应该只有通过证书认证的客户端才能访问。但是服务器在握手过程中并没有要求提供客户端证书(特别是因为不太旧的Web浏览器在被要求提供证书时显示出奇怪的弹出窗口,特别是如果他们没有证书的话,所以服务器会避免询问证书,如果它没有足够的理由相信客户有一个,并知道如何使用它)。
  • 因此,服务器触发新的握手,这次请求证书。

我刚刚描述的情况有一个有趣的弱点,有关解决方法,请参阅RFC 5746。从概念上讲,SSL只是以“前进”的方式传输安全特性。在做一个新的握手,什么可以知道有关客户端之前,新的握手仍然有效(例如,如果客户已在隧道内发送了良好的用户名+密码),而不是倒过来。在上面的情况中,之前收到的第一个HTTP请求新握手不会被第二次握手的基于证书的身份验证所覆盖,而且会被攻击者选中!不幸的是,一些Web服务器只是假设来自第二次握手的客户端认证延伸到了第二次握手之前发送的内容,并且允许来自攻击者的一些令人讨厌的技巧。RFC 5746试图解决这个问题。

警报

警报消息只是警告和错误消息。除非它们可以被一些攻击所破坏(见后面的内容),否则它们是无趣的。

这里一个重要的警告消息,称close_notify:这是一个消息,客户端或当它想关闭连接的服务器发送。在收到此消息后,服务器或客户端也必须回应,close_notify然后考虑关闭隧道(但会话仍然有效,并且可以在更简化的握手中重复使用)。有趣的部分是,像所有其他记录一样,这些警报消息由加密和MAC保护。因此,连接关闭由密码伞覆盖。

这在(旧)HTTP的上下文中很重要,其中一些数据可以由服务器发送而没有明确的“内容长度”:数据一直延伸到传输流的末尾。带有SSLv2的旧HTTP(它没有close_notify)允许攻击者强制关闭连接(在TCP层面),客户端可能需要关闭连接; 因此,攻击者可以截断数据而不被捕获。这是SSLv2(可以说是最糟糕的)和SSLv3修复它的问题之一。请注意,“现代”HTTP使用“Content-Length”标头和/或分块编码,即使SSL层允许它也不容易受到这种截断。不过,很高兴知道SSL为关闭事件提供保护。

攻击

Stack Exchange的答案长度有限制,所以对SSL的一些攻击的描述将在另一个答案中(此外,我还有一些煎饼做饭)。敬请关注。


在上一个答案中冗长的SSL呈现之后,让我们继续讨论有趣的内容,即:

攻击SSL

有很多针对SSL的攻击,其中一些针对实施错误,另一些针对真正的协议弱点。

我们必须记住,虽然SSL是受攻击最多的协议之一(因为它非常高调:SSL的成功应用在研究文章的摘要中看起来很不错),但SSL也是修复最多的协议之一。正是因为所有已知的攻击传输协议的方法都已经在SSL上进行了尝试,并且在适当的地方对SSL进行了修补,所以它被认为是稳健的。

版本回滚

在SSLv3的早期,SSLv2仍被广泛使用,因此客户端通常发送SSLv2兼容ClientHello消息,这仅表示SSLv3也受支持; 服务器会接受提示并以SSLv3 +方言进行响应(有关详细信息,请参阅RFC 2246的附录E )。由于SSLv2存在弱点,因此攻击者需要尽可能安排一个客户端和服务器,两者都知道SSLv3,然后使用SSLv2进行对话。这被称为版本回滚攻击。该概念也正式扩展到更高版本。

已添加Kludges以检测回滚尝试。对于返回到SSLv2的回退,知道SSLv3 +的客户端应该为RSA加密步骤使用特殊填充(SSLv2仅支持基于RSA的密钥交换):在PKCS#1中,要加密的数据应该是填充许多随机字节; 然后SSLv3感知的客户端应该将最后八个填充字节中的每一个设置为固定值0x03。服务器然后检查这些字节; 如果八0×03被发现,那么回滚时最有可能尝试,并且服务器拒绝尝试(一的SSLv2,仅客户端仅概率255 -8使用这种填充字节出的纯粹的运气不足,因此误报发生在可忽略不计的费率)。

对于旧版本的SSL / TLS的回滚,但不会比SSLv3旧,增加了另一个kludge:在客户端使用服务器的RSA密钥加密的48字节的预主密钥中,前两个字节不是随机的,但应该等于客户在其ClientHello消息中首先写入的“支持的最大协议版本” 。不幸的是,有些客户弄错了,这个kludge只适用于基于RSA的密钥交换,所以防止回滚的保护非常有限。幸运的是,SSLv3 +具有另一种更强大的防止回滚的保护措施,即握手消息在Finished消息被建立。这样可以防止回滚,除非“旧版本”会非常弱,以至于攻击者在握手结束之前可能完全打破整个加密。这还没有发生(SSLv3仍然相当健壮)。

弱密码套件

某些标准密码套件在某些方面故意弱。有:

  • 一些根本没有加密的密码套件,只有完整性检查,例如TLS_RSA_WITH_NULL_SHA;
  • 一些带有40位加密的TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5密码套件,例如(密码套件意图符合上个世纪严格的美国出口规则 – 这些法规在克林顿时代结束时已大部分取消);
  • 一些带有56位加密的密码套件,例如TLS_RSA_WITH_DES_CBC_SHA。使用现有技术,56位DES是可以破解的,但对于一个业余爱好者(即使是能够访问几百部大学机器的无聊学生),这仍然有点困难,所以我倾向于将56位DES限定为“中等强度”。

这为版本回滚攻击的变种打开了道路,攻击者强制客户端和服务器就弱密码套件达成一致意见,攻击者修改客户端公布的密码套件列表。如果选定的密码套件非常薄弱以致于可以将其分解以便重新计算明显正确的Finished消息,则这对于攻击者是可行的。实际上,SSLv3 +中使用的MAC(即使在基于MD5的情况下)足够强大以防止这种情况发生。所以这里没有实际的担心。另外,我的观点是,这里的任何真正的弱点都是当客户端或服务器接受使用弱密码套件时。

默认情况下,现代Web浏览器不允许使用这种弱密码套件。

私钥盗用

如果SSL连接使用RSA密钥交换和攻击者保持的记录副本,再后来就(可能几个月后,可能通过检查对废弃硬盘或磁带的所有备份)获得的私有密钥的副本,然后他可以解开握手并解密数据。

完美的前向保密是关于“稍后”的反击。你通过使用DHE密码套件得到它。使用DHE密码套件,可用于解除握手的实际私钥是短暂的Diffie-Hellman密钥,而不是服务器的RSA(或DSS)私钥。它是短暂的,它只存在于RAM中,并且从未写入硬盘; 因此,它应该更具有适应性。

所以这个教训是:一般来说,尽可能使用DHE密码套件。你仍然应该介意你的备份,不要让你的私钥泄漏,但至少,DHE套件使这样的泄漏少一点问题,特别是如果它发生在密钥生命期结束后(即相应的证书不是更长的有效期)。

证书祸害

整个证书业务是SSL的痛处。

从技术上讲,SSL与X.509完全独立。证书链被交换为不透明的斑点。在某些时候,客户端必须使用服务器的公钥,但客户端可以自由地以任何它认为合适的方式“知道”该密钥。在可以使用SSL的一些特定情况下,客户端已经知道服务器的公钥(在代码中硬编码)并且忽略服务器发送的证书。尽管如此,在HTTPS的常见情况下,客户端按照X.509中的描述验证服务器的证书链(以牺牲理智为代价读取;您已被警告)。

这产生了许多攻击媒介,例如:

  • 验证需要验证证书在当前日期仍然有效。客户端机器如何知道当前日期?通过它的内部时钟,并且可能通过与NTP服务器交流(以一种完全不受保护的方式!)。客户端可能会关闭几分钟,几小时,几天,甚至几年(我已经看到它),并且在某种程度上,强大的攻击者可能会通过摆弄NTP消息来强制它。这将允许攻击者使用多年前废除的过期证书。注意一个有趣的事实:SSL“客户端随机”和“服务器随机”应该包含28个随机字节和本地日期和时间(超过4个字节)。包含时间意味着成为针对基于时间的攻击的解决方案的一部分。我不知道有任何实际检查它的实现。
  • 截至2003年左右,在Internet Explorer / Windows中实施证书验证不能正确处理“基本限制”扩展。最终结果是,任何拥有100欧元证书的人都可以充当CA并使用任意选择的名称和密钥签发“证书”。
  • X.509包含了一个名为撤销的破坏限制功能:这是关于发布一个放逐证书列表,它看起来不错,加密地说,但不应该被信任(例如他们的私钥被盗,或者它们包含错误的名字)。撤销只在涉及的各方(即浏览器)接受下载庞大的撤销列表(可能有几兆字节!)或联系OCSP服务器时起作用。现在的浏览器现在这样做了,但有点不情愿,如果无法及时获取撤销状态信息(因为人类用户不耐心),许多人都会接受连接。多年来总体情况有所改善,但速度相当缓慢。
  • 一些根CA在过去犯了一些错误(例如Comodo和DigiNotar)。这导致发布伪造的证书(名字是,www.microsoft.com但私钥并不在微软手中……)。这些失误被发现,证书被撤销,但它仍然会引起一些令人不舒服的问题(例如,有没有其他CA有这样的问题,但没有透露它们,或者更糟糕的是,从来没有注意到它们?)。

X.509是一个非常复杂的算法,技术,规范和委员会的集合,很难做到这一点。试图用C这样的不受保护的编程语言“手动”解码X.509证书是一种获取缓冲区溢出的简单方法。

Bleichenbacher攻击

Daniel Bleichenbacher在1998年发现了一个针对RSA的好攻击。当您使用RSA加密一段数据(与ClientKeyExchangeSSL中的消息相同)时,必须填充要加密的数据以便生成与RSA模数相同长度的字节序列。填充主要由随机字节组成,但有一点结构(特别是,填充后的前两个字节必须是0x00 0x02)。

一旦解密(然后在服务器上),必须找到并移除填充。恰巧在那个时候,当服务器解密但获得了一个无效的填充(0x00 0x02字节不存在)时,它用一条警报消息(按照SSL规范)报告它,而有效的填充导致服务器使用看似解密的值并继续握手。

这种东西被称为填充预言。它允许攻击者发送任意字节序列,就好像它是一个加密的预主秘密,并知道该序列的解密是否会产生有效的填充。这仅仅是1位信息,但只需要几百万的请求就可以恢复私钥(使用巧妙的“加密”字符串)。

解决方法:解密导致无效填充时,服务器将继续使用随机的预主密钥。随后,握手将随着Finished信息而失败。所有当前的SSL实现都是这样做的。

填充Oracle反击

记录本身就是发现填充oracle的另一个领域。考虑CBC加密和HMAC。要加密的数据首先是MAC,然后结果被加密。使用CBC加密,要加密的数据的长度必须是块大小的倍数(3DES为8个字节,AES为16个字节)。因此,一些填充应用了一些结构。

那时(2002年,Vaudenay发现了这个攻击),当一个SSL实现处理一个接收到的记录时,它为这两个条件返回了不同的警报消息:

  • 解密后,找不到有效的填充结构。
  • 解密后,找到了一个有效的填充,但MAC被验证并且不匹配。

这是一个填充oracle,可以用来恢复一些加密的数据。它需要一个积极的攻击者,但并不那么难。Vaudenay实现了它,并且它扩展到了这种情况,即修改后的SSL实现在这两种情况下都返回了相同的警报消息,但由于重新计算MAC所花费的时间而花费更长时间返回(这是一个很好的演示定时攻击)。

因为人们从不学习,所以在Rizzo和Duong重新实现Vaudenay攻击并构建了一个恢复HTTP cookie的演示时,2010年(8年后),ASP.NET中使用的SSL的微软实施仍未得到修复

看到这个页面的一些指针。必须注意的是,如果SSL已经使用了加密 – 然后MAC,则可以避免这样的问题(即使在考虑解密之前,错误的记录也会在MAC级被拒绝)。

BEAST的袭击再次来自Duong和Rizzo,并且再一次,它是一次较老的攻击(2002年来自Philip Rogaway)的重制。为了得到这个想法,考虑CBC。在这种操作模式下,每个数据块首先与前一个块的加密结果异或; 这是加密XOR 的结果。这是为了“随机化”块并避免ECB模式下发现的泄漏。由于第一个块没有“前一个”块,因此必须有一个初始化向量(IV),它扮演着第一个块的前一个块的角色。

事实证明,如果攻击者可以控制要加密的部分数据,并且可以预测将要使用的IV,那么他可以将加密机变成另一个解密预言者并用它来恢复一些其他的加密数据(攻击者不会选择)。但是,在SSLv3和TLS 1.0中,攻击者可以预测IV记录:它是以前记录的最后一个块!因此,攻击者必须能够发送流中的一些数据,以便在实现构建并发送前一个记录的位置(通常是在累积了16 kB的数据时)“推送”目标数据,但没有开始建立下一个。

TLS 1.1+受到保护,因为在TLS 1.1(及后续版本)中,使用了每个记录的随机IV。对于SSLv3和TLS 1.0,一种解决方法是发送零长度记录:即,长度为零的有效载荷的记录 – 但是具有MAC和填充和加密,并且MAC是通过密钥和序列计算的数字,所以这扮演了一个随机数字发生器的角色。不幸的是,IE 6.0扼杀零长度记录。其他策略涉及1 / n-1拆分(一个n字节记录作为两个记录发送,其中一个包含一个有效负载字节,另一个包含剩余的n-1个记录)。

另一种解决方法是在可能的情况下强制使用非CBC密码套件 – 如果客户端发送的密码套件列表中有一个套件,服务器将选择基于RC4的密码套件,即使客户端首选a基于CBC的密码套件。这个工具可以告诉你,一个给定的服务器显然是这样的。(注意:BEAST是对客户端的攻击,但通过选择RC4密码套件,服务器可以保护粗心的客户端。)

看到这个页面的一些指针。虽然TLS 1.1是从2006年开始的,但BEAST攻击可能会迫使浏览器厂商最终升级。

犯罪

至于任何好莱坞特许经营,Duong和Rizzo在2012年发行了续集的续集。犯罪行为利用多年前理论化的漏洞,但只在他们最近发表的示范中生动地表现出来。CRIME在与BEAST攻击相同的设置中利用压缩(攻击者可以在SSL连接中发送其自己的一些数据,其中也发送诸如cookie的有趣目标数据)。粗略地说,攻击者将其数据放入目标字符串的潜在值,并且如果匹配,则压缩使得到的记录更短。看到这个问题(预认知)分析。

通过完全不使用TLS级别的压缩可以避免犯罪,这正是浏览器现在所做的。Internet Explorer和IIS从未实现过TLS级别的压缩功能(一次性,节省了一天的时间); Firefox和Chrome实施了它,并且在今年夏天停用了(他们被Duong和Rizzo预先警告,他们在活动中负有相当责任)。

CRIME显示了我为什么在我的SSL解释开头附近写道:

SSL实现这些目标的程度很大(但不是绝对的)。

事实上,加密会泄漏加密数据的长度。没有一个好的解决方案。单独的长度可以揭示很多事情。例如,当用网络监视器观察SSL连接时,我们可以发现流内的“额外握手”(因为每个记录的第一个字节标识了记录中的数据类型,并且没有加密)。根据记录的长度,很容易看出客户是否提供了证书。

贵宾犬

编辑:此部分已于2014-10-15添加)

“Poodle”攻击利用基于CBC密码套件的特定于SSL 3.0的缺陷。它依赖于SSL 3.0经常被忽视的特性:大多数填充字节被忽略。在TLS 1.0中,填充(在记录中添加的字节使长度与CBC加密兼容,只处理完整块)已完全指定; 所有的字节必须有一个特定的值,并且收件人检查。在SSL 3.0中,填充字节内容被忽略,这使得攻击者可以执行大部分未被注意的更改。这种变化只会影响非应用数据,但可以以与BEAST模糊的方式用作解密预言。

这个答案中可以阅读更多细节。

未来

人类从不学习。由于很多原因,一开始总是看起来不错,但是会给SSL添加漂亮的扩展带来很大的压力,但会导致额外的问题。

考虑一下,例如,SSL FalseStart。这主要是关于客户端在发送Finished消息之后(完全握手)发送其应用程序数据,而不等待Finished来自服务器的消息。这减少了延迟,这是好的和良好的意图。然而,它改变了安全情况:在Finished从服务器接收到消息之前,后者仅被隐式验证(客户端没有证据证明预期的服务器真的参与其中;它只是知道,无论它发送的都是可读的只有预期的服务器)。这可能会产生影响; 例如,攻击者可以效仿服务器直到该点并强制,例如,客户端使用基于CBC的密码套件或TLS压缩。因此,如果客户端实施FalseStart,那么它会降低针对BEAST和CRIME的保护措施的有效性,否则可能由服务器执行。

(谷歌今年春天禁用了FalseStart,显然是因为与某些服务器存在兼容性问题。无论如何,“减少30%的延迟”看起来很奇怪,因为FalseStart只会在完全握手时产生一些影响,而不是缩短握手时间,所以我不相信这些所谓的好处;至少不是那么重要。)

添加评论

友情链接:蝴蝶教程