有许多服务器支持出口级密码,仅仅是因为默认密码集具有,并且在某些情况下(莫名其妙地)继续启用它们。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 密钥交换的证书,但它可以被暴力分解。
可行的攻击涉及特定的服务器和客户端行为:
服务器必须支持带有 RSA 的导出级密码(可能默认启用)。使用此功能时,服务器还必须有一个可用的弱(<=512 位模数)密钥,它在使用其真实(强)密钥签名时保护模数。
服务器必须使用中长期临时 RSA 导出密钥(Apache 这样做),因为实时分解不可行。
攻击者必须通过建立出口级连接来获取弱 RSA 公共模数,然后在用新模数替换之前将模数分解(大约 8 小时,100 美元)。攻击者不能伪装成使用它的服务器,但如果客户端使用它,他可以解密用于服务器的数据。
攻击者必须 MITM 一个客户端,该客户端将错误地接受导出级密钥(RSA 模数),即使导出密码未启用,并且不在客户端握手中(损坏的 OpenSSL 和 Apple 客户端会这样做)。
- 攻击者必须修改 ClientHello 以仅包含 RSA 导出密码(在 TLS 中,服务器从客户端列表中选择密码),导出(临时)密钥必须由真实(长期)服务器密钥(攻击者不具有)。
- 攻击者必须修改 ServerHello 以使其满足客户端的期望(即使用原始 RSA 非导出密码之一)
- 攻击者使用弱 512 位模数发送(状态外)ServerKeyExchange,客户端将信任它,因为它已使用真实服务器密钥进行签名
- 客户端接受导出级 RSA 密钥,因为它出现在握手的正确阶段,由于存在缺陷,TLS 状态机对其进行处理,随后使用它而不是证书中的真实密钥。
攻击者获得pre-master secret,使用临时RSA密钥加密并由客户端发送,然后攻击者可以计算master secret(使用pre-master,以及之前握手中交换的其他数据)
现在攻击者掌握了主密钥,他可以计算并发送有效的“完成”消息,任何一方都无法检测到连接中的任何干扰。游戏结束。
这个问题是两件事的结合:
- 具有导出级密码支持的错误配置服务器,这需要使用弱临时 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)中完全取消。