鉴于 FREAK TLS 漏洞,为什么这么多服务器仍然提供 RSA-EXPORT 密钥?

信息安全 tls 攻击 中间人 蛮力
2021-08-14 09:02:04

Ars Technica 正在报告针对 HTTPS 的新攻击。被称为 FREAK,被报告为易受攻击的设备包括 iPhone、Android 设备和运行 OS X 的 Mac。攻击(如下所述 - 谢谢@bonsaiviking)是活动的 MITM 可以改变客户端和服务器之间的 TLS 协商仅向服务器提供 EXPORT 强度密码套件。这会诱使容纳服务器选择 EXPORT 强度密钥。MITM 然后确保返回给客户端的回复看起来正常,但仍使用较低强度的密钥。易受攻击的客户即使在协商期间没有提供该选项,也会接受这种较低强度的密钥。这显然不够安全,因此可能会被暴力破解。

为什么这些密钥在这么多设备和服务中仍然有效?尤其是 Apple 设备——我们都知道它们经常会快速淘汰过时的技术。我原以为一旦从美国放松加密货币的出口,这些弱密钥的提取速度就会比看起来要快得多。

进一步阅读:Matthew Green 的博客文章官方网站(在我发布时出现)Hacker News 线程

4个回答

虽然您的问题(为什么有这么多提供导出密码套件的服务器)是有效的,但您对问题的描述是错误的。怪胎是:

  • 一类客户端错误
  • 由于服务器端配置而可利用。

您列出的易受攻击的设备配置为使用出口级密码套件,但它们可以被欺骗使用标准(“全强度”)密码套件的出口级密钥长度。该方案的工作原理如下:

  1. 易受攻击的客户端发送包含支持的密码套件的明文 ClientHello 消息,其中没有一个是 EXPORT。
  2. 攻击者拦截 ClientHello 并用 EXPORT 替换密码套件。
  3. 服务器选择 EXPORT 密码套件之一,并以缩短长度的导出密钥进行响应。如果服务器未配置为使用 EXPORT 密码套件,则它会发出致命警报,并且连接会停止。
  4. 攻击者修改 ServerHello 响应以将 EXPORT 密码套件替换为非导出版本,但不理会弱密钥。
  5. 由于该错误,客户端接受导出密钥并协商弱化的 TLS 连接。

显然其中涉及更多微妙之处,马修格林很好地解释了它们,但这些都是基本事实。

这些键仍然有效,因为与许多其他事物一样,为了向后兼容,网络从根本上被破坏了。技术供应商经常在做正确的事情和支持现有的东西之间做出选择。

你能想象如果谷歌和苹果发布的网络浏览器不支持这个功能会引起轩然大波吗?责任不在于拒绝使用更现代技术的服务器,而在于苹果和谷歌。

我们在 90 年代的 Netscape/Internet Explorer 大战中看到了类似的东西

有许多服务器支持出口级密码,仅仅是因为默认密码集具有,并且在某些情况下(莫名其妙地)继续启用它们。TLS 1.1(第 A.5 节)中的一项更改是声明出口级密码不得在 TLSv1.1 中使用。TLS 1.0(第 D.4 节)由实现决定所需的安全级别。

Apache httpd 的默认值SSLCipherSuite是“DEFAULT”值,直到并包括 openssl-1.0.2,它将包括编译的几乎所有内容,仅不包括具有匿名身份验证或空加密的密码集。但是,从 httpd-2.4.7(2013 年 11 月)开始,导出等级(和 aNULL/eNULL)密码被 删除mod_ssl,并且无法使用 恢复SSLCipherSuite此更改未向后移植到 2.2。直到并包括 httpd-2.2.21(2011 年 9 月),默认配置文件显式启用了“LOW”密码,并且隐式启用了“EXPORT”(40),只有“EXPORT56”被禁用(可能是疏忽)。

问题的一个可能来源是运行相当最新的 Apache-2.2,但配置文件较旧。

不过,您对攻击的描述并不完整。“出口级”通常被解释为“小于 128 位”的意思。真正的出口级密码可能还需要在密钥交换中使用较短的出口级密钥/模数。SSL/TLS 密码中有两种不同类型的密钥,大多数人都会熟悉导出密码,因为它使用小型(40 位或 56 位)密钥。这仅指对称密钥大小,仅用于对称密码,例如 RC4 或 DES。另一种密钥类型是用于安全交换对称密钥的非对称密钥。

美国出口管制不影响只是对称密钥大小,它们会影响非对称密钥大小太:

加密出口管制:修订许可例外 ENC 和大众市场资格、提交程序、报告要求、许可申请要求以及在第 5 类第 2 部分中添加注释 4

[...]

a.1.a. 使用超过 56 位的密钥长度的“对称算法”;或者

a.1.b. 一种“非对称算法”,其中算法的安全性基于以下任何一项:

a.1.b.1。超过 512 位的整数因式分解(例如,RSA);

如果服务器具有 RSA 1024 位(或更大)密钥,则它不能与所有具有正常基于 RSA 的密钥交换(加密操作)的导出密码一起使用,它必须以某种方式降级为 512 位密钥。(不过,签名密钥的密钥可以大于 512 位。)

$ openssl ciphers -v "kRSA" | egrep "(512|1024)"
EXP1024-RC4-SHA         SSLv3 Kx=RSA(1024) Au=RSA  Enc=RC4(56)   Mac=SHA1 export
EXP1024-DES-CBC-SHA     SSLv3 Kx=RSA(1024) Au=RSA  Enc=DES(56)   Mac=SHA1 export
EXP1024-RC2-CBC-MD5     SSLv3 Kx=RSA(1024) Au=RSA  Enc=RC2(56)   Mac=MD5  export
EXP1024-RC4-MD5         SSLv3 Kx=RSA(1024) Au=RSA  Enc=RC4(56)   Mac=MD5  export
EXP-DES-CBC-SHA         SSLv3 Kx=RSA(512) Au=RSA  Enc=DES(40)   Mac=SHA1 export
EXP-RC2-CBC-MD5         SSLv3 Kx=RSA(512) Au=RSA  Enc=RC2(40)   Mac=MD5  export
EXP-RC4-MD5             SSLv3 Kx=RSA(512) Au=RSA  Enc=RC4(40)   Mac=MD5  export
EXP-RC2-CBC-MD5         SSLv2 Kx=RSA(512) Au=RSA  Enc=RC2(40)   Mac=MD5  export
EXP-RC4-MD5             SSLv2 Kx=RSA(512) Au=RSA  Enc=RC4(40)   Mac=MD5  export

kx=RSA(512)表示key-e x更改是固定大小的 RSA 512 位,与证书大小(或更准确地说,模数大小)无关。RSA 1024 位导出密码 (EXPORT56) 在这里不太有趣,但在与 2048 位或更高的证书一起使用时仍然是一个潜在的弱点(尽管它们早已从 OpenSSL 中删除)。

与散列输出或对称密钥不同,非对称密钥(模数)不能简单地切成两半(RSA 算法背后的数学不再成立),因此使用临时 RSA 密钥此密钥使用服务器真正的 RSA 密钥进行签名,并在可选的ServerkeyExchange(类型 0x0C)消息中进行交换。(DHE 密钥交换也会发生类似的步骤,因为单独的 RSA 证书不包含完成交换所需的数据。)

您可以使用以下导出密码看到这一点EXP-EDH-RSA-DES-CBC-SHA

$ openssl ciphers -v EXP-EDH-RSA-DES-CBC-SHA
EXP-EDH-RSA-DES-CBC-SHA SSLv3 Kx=DH(512)  Au=RSA  Enc=DES(40)   Mac=SHA1 export
^^^^^^^

这里有趣的部分是EXP-EDH,额外的 ServerKeyExchange 包含一个较短的(512 位)EDH 密钥。从Matthew Green 的讨论中不清楚DH 是否也是一个问题。RSA Kx一个问题,如果您捕获会话并运行它,您可以看到会发生什么ssldump

$ sudo tcpdump -s1520 -c 18 -w insecure-rsa.pcap host www.insecure.com and port 443 &
$ openssl s_client -showcerts -connect www.insecure.com:443 -cipher EXP-RC4-MD5 -msg
[...]
$ ssldump -VAN -r insecure-rsa.pcap
[...]
1 4  0.0245 (0.0000)  S>CV3.1(205)  Handshake
  ServerKeyExchange
    params
      RSA_modulus[64]=
        b4 3c e4 c5 f2 9b 8b 8e ef 6e 29 4e 5d 80 78 1c 
        1d e8 80 0f 65 32 a0 a6 be d4 35 a6 09 6b 2c 15 
        f2 80 e7 cd 22 9b 01 21 1e 7b 13 12 95 34 03 16 
        7b 9a 66 79 4e d1 6d 15 28 3d 73 45 91 85 a0 c1 
      RSA_exponent[3]=
        01 00 01 
    signature[128]=
      c6 09 b9 14 88 94 6d 06 82 84 e6 af eb af 72 fc 
      fd c6 d5 09 63 a8 f5 f8 e7 3a 79 69 14 9f 24 0e 
      ed dd 71 4b c4 8d 99 51 7c e6 1f aa af ea b2 b9 
      05 04 3c db 31 40 8d 11 f8 94 73 26 a5 5c 2f 28 
      84 49 77 62 3c 27 90 51 52 9f ab 61 6c 12 cd 49 
      9e ab ad f5 bf 2b f7 9c 1b 1e 05 a2 40 f6 7c 60 
      b3 8b 1d 8a 2f 4c bb 1e b0 04 ed 42 a8 14 95 55 
      7c b1 54 ff a2 3e e2 98 f4 15 96 7a 48 c4 a6 8c 

ssldump有点旧,有一些问题,但它适用于此。)

64 字节的 RSA 模数是这里的“512 位”问题,它相当于 RSA 密钥交换的证书,但它可以被暴力分解。

可行的攻击涉及特定的服务器和客户端行为:

  1. 服务器必须支持带有 RSA 的导出级密码(可能默认启用)。使用此功能时,服务器还必须有一个可用的弱(<=512 位模数)密钥,它在使用其真实(强)密钥签名时保护模数。

  2. 服务器必须使用中长期临时 RSA 导出密钥(Apache 这样做),因为实时分解不可行。

  3. 攻击者必须通过建立出口级连接来获取弱 RSA 公共模数,然后在用新模数替换之前将模数分解(大约 8 小时,100 美元)。攻击者不能伪装成使用它的服务器,但如果客户端使用它,他可以解密用于服务器的数据。

  4. 攻击者必须 MITM 一个客户端,该客户端将错误地接受导出级密钥(RSA 模数),即使导出密码未启用,并且不在客户端握手中(损坏的 OpenSSL 和 Apple 客户端会这样做)。

    • 攻击者必须修改 ClientHello 以仅包含 RSA 导出密码(在 TLS 中,服务器从客户端列表中选择密码),导出(临时)密钥必须由真实(长期)服务器密钥(攻击者不具有)。
    • 攻击者必须修改 ServerHello 以使其满足客户端的期望(即使用原始 RSA 非导出密码之一)
    • 攻击者使用弱 512 位模数发送(状态外)ServerKeyExchange,客户端将信任它,因为它已使用真实服务器密钥进行签名
    • 客户端接受导出级 RSA 密钥,因为它出现在握手的正确阶段,由于存在缺陷,TLS 状态机对其进行处理,随后使用它而不是证书中的真实密钥。
  5. 攻击者获得pre-master secret,使用临时RSA密钥加密并由客户端发送,然后攻击者可以计算master secret(使用pre-master,以及之前握手中交换的其他数据)

  6. 现在攻击者掌握了主密钥,他可以计算并发送有效的“完成”消息,任何一方都无法检测到连接中的任何干扰。游戏结束。

这个问题是两件事的结合:

  • 具有导出级密码支持的错误配置服务器,这需要使用弱临时 RSA 密钥
  • 一个有缺陷的客户端,它接受握手中指示的导出密码,即使它没有使用它启动连接。(客户端不需要配置为提供密码,但客户端的 SSL/TLS 库必须具有实现。)

(还有另一个问题,由于使用了导出级密码,每个客户端连接可能是暴力破解的,因为它只有 40 位或 56 位,但破坏 RSA 部分更有用和有趣。)

从历史上看,为 RSA 密钥生成素数需要时间,这大概就是 Apache 在启动时只生成一次的原因。在当代硬件上,最多只需要几个额外的毫秒。旧的 Apache-ssl 源代码(apache-1.3.x 时代,早于 mod_ssl-2.0)中,您会发现这个幽默的参​​考:

#if SSLEAY_VERSION_NUMBER >= 0x0920
/* FIXME: This ought to generate a new key from time to time - why make the
Feds' life easy? */
static RSA *TmpRSACallback(SSL *pSSL,int nExport,int nKeyLength)
{
static RSA *pRSA512=NULL;
static RSA *pRSA1024=NULL;

ap_log_error(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,
         SSL_get_ex_data(pSSL,EX_DATA_SERVER_REC),
         "Generating %d bit key",nKeyLength);

这个 FIXME 从未修复,即使在带有mod_ssl-2.8的 Apache-1.3 中,它自由引用(并忽略)了 TLS 规范关于密钥重用/再生的建议。最后,导出 RSA 支持于2013 年 9 月在 dev 分支(将是 httpd-2.5)中完全取消。

删除诸如支持导出密码之类的旧内容通常被视为一种节省成本的措施,因此不必维护代码。像这样的旧代码通常就像一艘潜艇。除非它让自己为人所知,或者除非有人专门寻找它,否则很难检测到。它变得像一个附录。相对没用,没有它也很容易生活,但去除它需要努力。保持它不需要任何努力。除非有人积极思考这个问题,否则努力通常不会获胜,这需要知道它是否存在。

在这一点上,向后兼容性的权衡基本上是不存在的。美国密码出口法在大约 20 年前的 1996 年基本上被取消。从那时起,服务器已经支持强密码多年,而仅支持这种弱密码的服务器数量肯定非常少。