Adam Innes · Blog

Logjam: Kill Export Diffie-Hellman and Bring Your Own Group

· 7 min · security, tls, nginx, apache

Last Wednesday, May 20, researchers from Inria, Microsoft Research, Johns Hopkins, the University of Michigan and the University of Pennsylvania published Logjam, tracked as CVE-2015-4000. It comes in two parts. The first is a flaw in TLS that lets an attacker in the middle push a connection down to 512-bit “export grade” Diffie-Hellman and break it while the handshake is still going. The second is less flashy and probably matters more: almost everyone uses the same handful of Diffie-Hellman primes, and that makes breaking them far cheaper than most of us assumed. Both have fixes that live in your server config.

What the attack needs

Export suites are a leftover from 1990s US export rules. SSL 3.0 and TLS 1.0 included DHE_EXPORT suites limited to primes of 512 bits or less, with messages otherwise identical to normal ephemeral Diffie-Hellman (DHE). The rules are long gone, but plenty of servers still offer them.

The NVD entry for CVE-2015-4000 sums up the flaw. When a server has DHE_EXPORT enabled and the client doesn’t, TLS 1.2 and earlier don’t properly convey that choice, so a man in the middle can rewrite the ClientHello to ask for DHE_EXPORT and then rewrite the ServerHello to say plain DHE.

The paper, Imperfect Forward Secrecy: How Diffie-Hellman Fails in Practice, explains why the client falls for it. The server signs its Diffie-Hellman values (the prime, the generator and its public value) with its certificate key, but the signed part doesn’t say which cipher suite it picked. So the browser gets a validly signed key exchange with a 512-bit prime and has no way to tell it came from an export suite.

Diagram of an attacker rewriting ClientHello and ServerHello so a browser accepts a 512-bit export group

The Finished messages at the end of the handshake cover each side’s view of it, and those views don’t match. But an attacker who works out the server’s secret exponent can compute the session keys and forge the server’s Finished message. So the attacker has to be an active man in the middle, your server has to accept DHE_EXPORT, the client has to accept a 512-bit group (Internet Explorer, Chrome, Firefox and Opera all did in the researchers’ testing), and the math has to finish before the client gives up. The paper lists ways around that last one: command line clients like curl and git often run with long timeouts, TLS warning alerts kept Firefox’s handshakes alive indefinitely in their tests, and browsers using TLS False Start with DHE send data such as cookies or passwords before the server’s Finished message arrives, so it can be recorded and decrypted later.

Why shared primes make it cheap

The best known way to break Diffie-Hellman over a prime is the number field sieve, and its first three stages, polynomial selection, sieving and linear algebra, depend only on the prime. Only the last stage, called descent, involves the key exchange you actually want to break. The expensive part happens once per prime, and every connection using that prime afterwards is cheap.

For a 512-bit group, the researchers’ precomputation took about a week, and after that individual key exchanges fell in roughly a minute or two. According to the paper, 8.4% of the Alexa Top 1 Million HTTPS domains supported DHE_EXPORT, and 82% of those vulnerable servers used a single 512-bit group, hard coded into Apache httpd from 2.1.5 in 2005 until 2.4.7, which disabled export suites. One precomputation let them compromise connections to 7% of the top million sites.

Diagram showing number field sieve precomputation done once per prime, then cheap descent for each connection to any server sharing that prime

The same logic scales up with a much bigger bill. The paper estimates 768-bit groups are within reach of academic teams and 1024-bit groups plausibly within reach of a nation state, at around 45 million core years of precomputation. The Logjam site says breaking the single most common 1024-bit prime used by web servers would allow passive eavesdropping on 18% of the Top 1 Million HTTPS domains, and a second prime would cover 66% of VPN servers and 26% of SSH servers. No downgrade needed.

The OpenSSL team’s post on Logjam adds that once the precomputation is done, old sessions using the same parameters can be decrypted fairly cheaply too. That stings, since forward secrecy is why DHE got popular in the first place.

First, turn off export suites

The researchers’ guide to deploying Diffie-Hellman for TLS says no modern clients rely on export suites and there’s little downside in disabling them.

The OpenSSL post says export suites are already out of OpenSSL’s defaults as of 1.0.2a and 1.0.1m, released in March. That only helps if your server uses the default cipher list, and most TLS configs set their own.

On nginx, the default ssl_ciphers is HIGH:!aNULL:!MD5, and export suites aren’t HIGH, since OpenSSL defines them as the 40 and 56 bit algorithms. If you set your own string, check it, because the example on nginx’s own documentation page ends with +EXP. Feed your string to the same OpenSSL your server uses; export suite names all start with EXP, so this should print nothing:

openssl ciphers -v 'HIGH:!aNULL:!MD5' | grep EXP

Apache 2.4.7 and later is covered, since its changelog says mod_ssl unconditionally disables export ciphers and SSLCipherSuite can’t turn them back on. Apache 2.2 is the one to worry about. Its documented default SSLCipherSuite is ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP, which includes export suites (ALL pulls them in, and +EXP just moves them to the back). Adding !EXP to the end of your SSLCipherSuite removes them.

Then generate your own 2048-bit group

When the guide went up last week, its advice was to generate a unique Diffie-Hellman group of 2048 bits or more for each server:

openssl dhparam -out dhparams.pem 2048

Don’t leave off the 2048. The OpenSSL post notes dhparam defaults to 2048 bits only in 1.0.2, and in the 1.0.1m source the default is still 512. Finding a safe prime can take a while, so let it run.

On nginx, the ssl_dhparam directive takes the file in the http or server context and has been around since 0.7.2:

ssl_dhparam /etc/nginx/dhparams.pem;

This matters even without export suites. The docs don’t say what happens if you skip it, but the nginx 1.8.0 source falls back to a 1024-bit group compiled into nginx, and the same code goes back to 1.0.0. So every one of those servers that never set ssl_dhparam shares one 1024-bit prime.

On Apache 2.4.8 or later with OpenSSL 1.0.2 or later, SSLOpenSSLConfCmd passes commands to OpenSSL’s configuration API, and OpenSSL 1.0.2’s DHParameters command loads a parameter file:

SSLOpenSSLConfCmd DHParameters "/etc/ssl/dhparams.pem"

Otherwise, the mod_ssl docs for SSLCertificateFile say that from 2.4.7 the certificate file can also hold DH parameters generated by openssl dhparam, so append dhparams.pem to it. Only the first SSLCertificateFile is read for them. Without custom parameters, 2.4.7 and later pick a standard group by certificate key size, the 2048-bit group from RFC 3526 for a 2048-bit key, and the 2.4.12 source falls back to a standard 1024-bit group for smaller keys. Standard groups are shared by definition, which is what the guide says to avoid.

Apache 2.2 is stuck again. Its SSLCertificateFile docs say nothing about DH parameters, and the 2.2.29 source hands out built-in 512-bit and 1024-bit groups. If you can’t move to 2.4, lean on elliptic curve suites instead (the 2.2 docs list ECC support from 2.2.26).

Diagram of where nginx and Apache get their default Diffie-Hellman group, compared with a group you generate yourself

Prefer ECDHE

The guide also recommends elliptic curve Diffie-Hellman (ECDHE). It says ECDHE avoids all known feasible cryptanalytic attacks, modern browsers already prefer it, the attacks on normal Diffie-Hellman groups don’t gain as much from precomputation, and servers don’t need unique curves. The paper also calls elliptic curves the long term fix.

In practice that means ECDHE suites first, DHE with your own group as a fallback, and the server’s order enforced with ssl_prefer_server_ciphers on in nginx or SSLHonorCipherOrder on in Apache. The guide has a full cipher string for each. On Apache 2.2 you could drop DHE suites entirely, since you can’t replace its built-in groups, and the researchers’ server test counts a server that supports ECDHE and doesn’t use DHE as safe from Logjam.

What might break

Mostly Java. The OpenSSL post says Java 7 based clients reject groups larger than 1024 bits, and the Apache docs warn about handshake failures with Java 7 or earlier. If you must keep a 1024-bit group for them, OpenSSL’s advice is to generate a fresh one rather than use your server’s built-in default.

Clients are moving too. OpenSSL’s next releases will reject DH parameters shorter than 768 bits, with 1024 to follow, and the Logjam site says Chrome, Firefox, Internet Explorer and Safari are all deploying fixes, so a 512-bit or 768-bit group is about to stop working.

Checking your server

The OpenSSL post has a smoke test using OpenSSL 1.0.2 tools. Connect with only DHE suites and look at the temporary key:

openssl s_client -connect example.com:443 -cipher "EDH" | grep "Server Temp Key"

You want at least DH, 2048 bits, and OpenSSL says anything under 1024 bits may already be in trouble. Older clients don’t print that line, so an empty result from 1.0.1 tells you nothing. If the connection fails, your server doesn’t do DHE, so check ECDHE works instead:

openssl s_client -connect example.com:443 -cipher "ECDHE"

Then confirm export suites are gone. This one should fail:

openssl s_client -connect example.com:443 -cipher "EXP"

These show the group’s size, not whether it’s shared, but the server test in the researchers’ guide also warns about commonly shared 1024-bit groups. Check every TLS endpoint, including mail: the paper found DHE_EXPORT on 14.8% of the SMTP servers it scanned, and no browser will warn you about those.

The takeaway

Logjam is another bill for 1990s export crypto, like FREAK in March, but the lasting lesson is about defaults. The 512-bit break worked because one hard coded group was everywhere, and the scary 1024-bit numbers are the same pattern at a bigger size. Turn off export suites, prefer ECDHE, give DHE a 2048-bit group only your server uses, and check the result with s_client.

← all posts