Pár poznámek z řešení nedávného problému. Používejte jen na vlastní nebezpečí.
Symptom
Hláška prohlížeče: Při spojení s host:port nastala chyba. Při komunikaci protokolem SSL byl v inicializační zprávě typu Server Key Exchange obdržen slabý klíč typu Diffie-Hellman. Kód chyby: SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY
Důvod
Krátké DH se dají napadnout pomocí Logjam útoku, proto jsou ve většině nástrojů zakázány nebo deprecated.
Diagnóza
openssl detekuje slabou DH touto hláškou:
openssl s_client -connect host:port -cipher "EDH"
140284808136336:error:14082174:SSL routines:SSL3_CHECK_CERT_AND_ALGORITHM:dh key too small:s3_clnt.c:3435:
Explicitně vypíše openssl sílu DH jen někdy:
s_client displays Server Temp Key info only on successful handshake (and only in version 1.0.2 up
Pak by to mělo jít vypsat takhle:
openssl s_client -connect host:port -cipher "EDH" 2>/dev/null | grep -ie "Server .* key"
Server Temp Key: DH, 1024 bits
Konkrétní hodnotu je možné zjistit jen ruční analýzou zpráv:
openssl s_client -msg -connect host:port
<<< TLS 1.0 Handshake [length 022c], ServerKeyExchange 0c 00 02 28 00 60 e9 e6 42 59 9d 35 5f 37 c9 7f fd 35 67 12 0b 8e 25 c9 cd 43 e9 27 b3 a9 67 0f be c5 d8 90 14 19 22 d2 c3 b3 ad 24 80 09 37 99 86 9d 1e 84 6a ab 49 fa b0 ad 26 d2 ce 6a 22 21
- Kde
0c 00 02 28
je kód zprávy ServerKeyExchange 0c s délkou 00 02 28. - Následující dva bajty
00 60
jsou délka modulu DH. Měla by to být hodnota alespoň01 00
, tedy 256 bytů, tzn. modulus má 2041 - 2048 bitů.
Ještě delší rozbor je zde
Java
Defaultní velikost DH byla zvýšena na 2048 až v Java SE 6u105 i když s délkou DH se hýbalo už asi i dřív a proto je pro dřívější verze potřeba to udělat ručně.
vim jdk1.6.0_75/jre/lib/security/java.security
-jdk.tls.disabledAlgorithms=... +jdk.tls.disabledAlgorithms=..., DH keySize < 2048
V Java 8 je možné zadat délku DH jako systémový parametr -Djdk.tls.ephemeralDHKeySize=2048
, více popsáno zde.
Aplikační server
Servlet kontejner (konkrétně Tomcat a odvozeniny) může opravu v konfiguraci Java ignorovat z různých důvodů:
- Je použitý nativní APR konektor, pak se použije systémové OpenSSL nastavení + konfigurace konektoru
- Verze Javy nebo JCE nepodporuje příslušné konfigurační direktivy nebo šifry
Je pak nutné opravovat SSL přímo v nastavení konektoru aplikačního serveru:
vim /.../jboss/server/default/deploy/jbossweb.sar/server.xml
Nejspolehlivější je úplně vypustit z povolených šifer DH bez eliptických křivek (s EC je dostatečně bezpečný menší klíč). Toto může sice pro starší prohlížeče vypnout forward secrecy, ale aplikace bude alespoň fungovat.
<Connector protocol="HTTP/1.1" SSLEnabled="true" port="443" address="${jboss.bind.address}" scheme="https" secure="true" clientAuth="false" keystoreFile=".../keystore.jks" keystorePass="..." sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2" ciphers="TLS_ECDHE..." />