There are many servers which support export-grade ciphers simply because default cipher sets had, and in some cases (inexplicably) continue to have them enabled. One of the changes in TLS 1.1 (section A.5) was to state that export grade ciphers MUST NOT be used in TLSv1.1. TLS 1.0 (section D.4) leaves it up to the implementation to decide on the required level of security.
Apache httpd's default
SSLCipherSuite is the value "DEFAULT", which up to and including openssl-1.0.2, would include just about everything compiled in, excluding only ciphers sets with anonymous-authentication or null encryption. However, as of httpd-2.4.7 (Nov 2013) the export grade (and aNULL/eNULL) ciphers are removed by
mod_ssl, and cannot be restored using
SSLCipherSuite. This change was not back-ported to 2.2. Up to and including httpd-2.2.21 (Sept 2011) the default configuration file had "LOW" ciphers explicitly enabled, and "EXPORT" (40) implicitly enabled, only "EXPORT56" are disabled (possibly an oversight).
A likely source of problems is someone running a reasonably up-to-date Apache-2.2, but with an older configuration file.
Your description of the attack isn't quite complete though. "Export grade" is often interpreted as meaning "less than 128-bit". A true export-grade cipher may also require the use of a shorter export grade key/modulus in key exchange. There are two distinct types of keys in an SSL/TLS cipher, most people will be familiar with the export ciphers as using small (40-bit or 56-bit) keys. This refers only to the symmetric key size, used only for the symmetric cipher such RC4 or DES. The other key type is the asymmetric key used to securely exchange the symmetric key.
The U.S. Export controls do not affect just symmetric cipher key size, they affect the asymmetric key size too:
Encryption Export Controls: Revision of License Exception ENC and Mass Market Eligibility, Submission Procedures, Reporting Requirements, License Application
Requirements, and Addition of Note 4 to Category 5, Part 2
a.1.a. A “symmetric algorithm” employing a key length in excess of 56-bits; or
a.1.b. An “asymmetric algorithm” where the security of the algorithm is based on any of the following:
a.1.b.1. Factorization of integers in excess of 512 bits (e.g., RSA);
If a server has an RSA 1024-bit (or larger) key, it cannot be used with all export ciphers with normal RSA-based key exchange (an encryption operation), it must be downgraded somehow to a 512-bit key. (Signing keys can key larger than 512-bits though.)
$ 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) means the key-exchange is a fixed size RSA 512-bit, independent of the certificate size (or more correctly, modulus size). The RSA 1024-bit export ciphers (EXPORT56) are less interesting here, but are still a potential weakness when used with 2048-bit or higher certificates (they have long since been removed from OpenSSL though).
Unlike a hash output or symmetric key, an asymmetric key (modulus) cannot simply be chopped in half (the mathematics behind the RSA algorithm would no longer hold), so instead a temporary RSA key is used. This key is signed with the servers real RSA key, and exchanged in an optional ServerkeyExchange (type 0x0C) message. (A similar step happens with DHE key exchange, as the RSA certificate alone does not contain the data needed to complete the exchange.)
You can see this with an export cipher like
$ 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
The interesting part here is
EXP-EDH, the extra ServerKeyExchange contains a shorter (512 bit) EDH key. It's not clear from Matthew Green's discussion if DH is also a problem. RSA Kx is a problem, you can see what happens if you capture a session and run it through
$ 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
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
01 00 01
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 is a little old, and has a few problems, but it works fine for this.)
The RSA modulus of 64 bytes is the "512-bit" problem here, it's equivalent to a certificate for RSA key exchange, but it can be brute-force factorised.
A viable attack involves specific server and client behaviour:
- The server must support an export-grade cipher with RSA (possibly enabled by default).
When this is used, the server must also have a weak (<=512-bit modulus) key available, it protects the modulus when used by signing with its real (strong) key.
- The server must use a medium to long-term temporary RSA-export key (Apache does this) since real-time factorisation isn't viable.
- The attacker must obtain the weak RSA public modulus by establishing an export grade connection, and then factor the modulus (approx 8 hours, $100) before it's replaced with a new one. The attacker cannot masquerade as the server using this, but he can decrypt data intended for the server if a client uses it.
The attacker must MITM a client who will erroneously accept an export grade key (RSA modulus), even if export ciphers are not enabled, and were not in the client handshake (broken OpenSSL and Apple clients do this).
- The attacker must modify the ClientHello to include only RSA export ciphers (in TLS, the server picks the cipher from the client list), the export (temporary) key must be signed by the real (long-term) server key (which the attacker does not have).
- The attacker must modify the ServerHello so that it meets the clients expectations (i.e. using one of the original RSA non-export ciphers)
- The attacker sends the (out of state) ServerKeyExchange with the weak 512-bit modulus, the client will trust this since it's been signed with the real server key
- The client accepts the export grade RSA key because it appears at the correct stage in the handshake, the TLS state-machine processes it due to a flaw and subsequently uses it instead of the real one in the certificate.
- The attacker obtains the pre-master secret, it is encrypted with the temporary RSA key and sent by the client, the attacker can then compute the master secret (using the pre-master, and other data exchanged earlier in the handshake)
- Now the attacker has the master secret, he can compute and send valid "finished" messages, neither side is able to detect any interference in the connection. Game Over.
This problem is a combination of two things:
- a mis-configured server with export grade cipher support, this necessitates the use of weak temporary RSA keys
- a flawed client which accepts the export cipher indicated in a handshake even though it did not initiate a connection using it. (The client need not be configured to offer the cipher, but the client's SSL/TLS library must have the implementation present.)
(There's another problem too, by virtue of an export grade cipher being used, each client connection may be brute-forced as it's only 40- or 56-bit, but breaking the RSA part is more useful and interesting.)
Historically, generating the primes for an RSA key took time, which is presumably why Apache only generates this once on startup. On contemporary hardware it takes only a few extra ms at most. In the old Apache-ssl source (apache-1.3.x era, predating mod_ssl-2.0) you'll find this humourous reference:
#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;
"Generating %d bit key",nKeyLength);
This FIXME was never fixed, even in Apache-1.3 with mod_ssl-2.8 which freely quoted (and ignored) the TLS spec's recommendation on key reuse/regeneration. Finally, export RSA support was ripped out entirely in September 2013 in the dev branch (which will be httpd-2.5).