2015-02-03, bewerkt op 2017-01-01

Veilige SSL/TLS-config voor servers

Het is tegenwoordig belangrijk om aandacht te besteden aan de SSL-config van je server(s), omdat met de standaard config van veel serversoftware nogal wat exploits mogelijk zijn: te denken valt aan het feit dat standaard de RC4-cipher gewoon aanstaat terwijl die tegenwoordig als zeer zwak wordt beschouwd, dat SSLv3 gewoon ondersteund wordt terwijl die kwetsbaar is voor de POODLE-attack, en dat met de standaard config geen Perfect Forward Secrecy (PFS) gerealiseerd wordt.

In dit artikel zal ik uitleggen wat er nodig is om je SSL-configuratie server-side goed af te stellen. Als benchmark is is Qualys' SSL Labs erg nuttig; het streven is om op deze benchmark de hoogst mogelijke score (A+) te halen. Hiervoor is naast een goede server-side config een een goed certificaat nodig, met onderstaande eisen:

  • Signed door een vertrouwde public CA (dus niet self-signed)
  • Sterk signature-algoritme (dus SHA-2 in plaats van SHA-1 of MD5)
  • RSA-key die groot genoeg is (2048 of 4096 bits)

Om een hoge score te halen op SSL Labs (en dit een veilige config te krijgen) moeten we een aantal dingen doen.

SSLv2 en SSLv3 uitschakelen

Deze twee oude versies van het SSL-protocol zijn kwetsbaar en worden tegenwoordig nauwelijks gebruikt. Het is wegens veiligheidsrisico's absoluut noodzakelijk deze uit te schakelen. Het is aanlokkelijk om ook TLSv1 uit te schakelen (recente browsers ondersteunen immers al lang TLSv1.2 danwel TLSv1.1), maar hierdoor zul je toch in de problemen komen omdat crawlers zoals Googlebot niet hoger dan TLSv1 ondersteunen.

UPDATE: Sinds eind februari 2015 ondersteunt Googlebot ook TLSv1.2. Hiermee is het eindelijk haalbaar om alles behalve TLSv1.2 uit te schakelen.

De cipher suite iets strakker afstellen

Een cipher suite bestaat uit een combinatie van een key-exchange-algoritme, een public-key encryptiealgoritme (dat wordt gebruikt voor authenticatie), een bulk-cipher (die wordt gebruikt om de message stream zelf te encrypten, nadat de handshake klaar is) en een MAC (Message Authentication Code), een cryptografische hashfunctie.

Als key-exchange-algoritme gaan we alleen de ephemeral (tijdelijke) varianten van Diffie-Hellman en Elliptic-Curve-Diffie-Hellman toestaan. Het is ook mogelijk om simpelweg géén (extra) key-exchange-algoritme zoals DH te gebruiken. In dat geval wordt de primary master-key simpelweg over RSA afgesproken. Het probleem hiermee is dat het later in de toekomst potentieel mogelijk wordt om alle 'gesprekken' versleuteld met dit certificaat te decrypten als je de private key in handen krijgt of kraakt. Met andere woorden: het biedt geen forward secrecy (FS). Wij willen graag PFS dus gebruiken we EECDH en EDH. Voor meer informatie over forward secrecy kan ik je deze goede uitleg aanraden.

Voor de authenticatie hebben we eigenlijk niet veel andere keus dan RSA: alternatieve algoritmen zoals Elliptic-Curve-Digital-Signature-Algoritm (ECDSA) bestaan wel, maar het authenticatie-algoritme moet ook ondersteund worden door het certificaat. Op dit moment geven nog erg weinig CA's certificaten uit met ECDSA. Als je wel zo'n certificaat hebt met ECDSA-keys, is het uiteraard een goed idee om dit algoritme in je cipher suite op te nemen.

Als bulk-cipher gebruiken we Advanced Encryption Standard (AES). Deze keus is simpel: het is momenteel momenteel algemeen aanvaard de beste symmetrische cipher. We gaan hier voor een keysize van 256 bits, AES-256 dus. AES-256 is tot zover bekend praktisch onmogelijk te kraken; brute-forcen zou je langer duren dan de leeftijd van het universum. We gebruiken geen DES of RC4 omdat deze ciphers onveilig zijn, en geen 3DES omdat dit traag is vergeleken met AES.

Tenslotte gebruiken we SHA-1 of SHA-384 als MAC.

Al met al komen we uit op de volgende cipher suite (in OpenSSL-syntax):

EECDH+aRSA+AES256:EDH+aRSA+AES256:@STRENGTH

TLS-compressie uitschakelen

Er bestaat en gevaarlijke exploit tegen SSL/TLS wanneer compressie gebruikt wordt. Deze exploit staat bekend als de CRIME-attack, en stelt kwaadwillenden in staat om versleutelde data te ontsleutelen door meerdere slimbedachte pakketjes naar een server te sturen en het (gecomprimeerde) antwoord van de server te onderzoeken. Uit de grootte van het antwoord kan dan na een aantal pogingen de versleutelde, geheime data worden afgeleid.

De enige beveiliging tegen deze attack is het uitschakelen van TLS-compressie, wat we dan ook gaan doen.

HTST inschakelen

Een belangrijke 'tekortkoming' van https zonder HTST is de stripping attack: hierbij kan een Man-in-the-Middle (MitM) de client doorsturen naar onversleutelde (http) versie van de website in plaats van de https-versie. Daarom is Hyper-Text Strict Transport (HTST) in het leven geroepen: een HTTP-header die de client bij een verbindingspoging vertelt dat de opgevraagde site enkel en alleen via https mag worden benaderd. Het is daarna aan de browser om die header te honoreren, iets wat bij recente browsers gelukkig gebeurt.

Er is wel enige voorzichtigheid geboden bij het gebruik van deze header: als je hem per ongeluk inschakelt op een domein waar je geen SSL-certificaat voor hebt, en de site in kwestie is drukbezocht, kan het zo maar gebeuren dat dat domein voor lange tijd onbereikbaar is door browsers die deze header hebben ontvangen. Een gebruikelijke TTL voor deze header is 15768000 seconden, wel een half jaar lang dus.

Compatibiliteit

Het uitschakelen van deze verouderde protocollen en ciphers betekent helaas wel onvermijdelijk dat oude clients niet meer ondersteund zullen worden. Toch hoef je je hier niet druk over te maken; het is niet verantwoord om de beveiliging van recente clients onder spel te zetten omdat je graag oude clients (die gewoon nodig eens moeten gaan updaten!) wilt blijven ondersteunen. Daarnaast zal je site het op die clients toch al niet doen als je VirtualHosts gebruikt omdat deze clients zelfs geen SNI (wat nodig is om SSL te gebruiken in combinatie met VirtualHosts) ondersteunen.

Met bovenstaande besluiten omtrent cipher suites en protocollen gaat het om de volgende clients die niet meer ondersteunt worden:

  • Android 2.3.7 (geen SNI, geen AES-256)
  • IE @ WinXP (geen SNI, geen AES)
  • Java 6 (geen SNI, geen AES-256)
  • Java 7/8 (geen AES-256)

Wil je per se Java ondersteunen, dan zul je AES-128 moeten inschakelen. Dit zorgt er wel voor dat je niet de maximale score krijgt op SSL Labs.

Als je besluit om enkel TLSv1.2 te ondersteunen, raak je bovenop de bovenstaande browsers nog meer browsersupport kwijt. Het gaat hier om:

  • Android t/m 4.3
  • Baidu crawler
  • IE t/m 10
  • Safari 5/6 @ OS/X

Merk op dat het in het geval van Android alleen gaat om de ingebouwde SSL-implementatie, die o.a. gebruikt wordt door de 'oude' stockbrowser. Alternatieve browsers en de meeste apps gebruiken echter hun eigen SSL-implementatie en tegenwoordig wordt op Android-devices steeds vaker Chrome meegeleverd als standaard browser in plaats van de stockbrowser.

Apache2

We beginnen met het stuk serversoftware dat het meest gebruikt zal worden met SSL: Apache. De configfile waar we in geinteresseerd zijn is /etc/apache2/mods-enabled/ssl.conf. De directives die je wilt aanpassen/toevoegen (binnen de IfModule) zijn:

SSLProtocol                      All -SSLv2 -SSLv3
SSLCipherSuite                   EECDH+aRSA+AES256:EDH+aRSA+AES256:@STRENGTH
SSLHonorCipherOrder              on
SSLCompression                   off

SSLUseStapling                   on
SSLStaplingResponderTimeout      5
SSLStaplingReturnResponderErrors off
SSLStaplingCache                 shmcb:/var/run/ocsp(128000)

Header always set Strict-Transport-Security "max-age=15768000; preload"

Gebruik in het geval dat je alleen TLS wilt ondersteunen de optie

SSLProtocol             TLSv1.2

Postfix

/etc/postfix/main.cf

smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_protocols = !SSLv2,!SSLv3
smtpd_tls_ciphers = high
tls_high_cipherlist = EECDH+aRSA+AES:EDH+aRSA+AES:@STRENGTH

Bovenstaande config zorgt ervoor dat TLS voor ESMTP niet verplicht is (dat zou geen goed idee zijn omdat veel MTA's het niet ondersteunen), maar dat AUTH wél verplicht over een versleuteld kanaal moet plaatsvinden. Ook hier schakelen we SSLv2 en SSLv3 weer uit en stellen we de hierboven-afgesproken cipher suite in.

Dovecot

/etc/dovecot/conf.d/10-ssl.conf

ssl = required
ssl_protocols = !SSLv2 !SSLv3
ssl_cipher_list = EECDH+aRSA+AES:EDH+aRSA+AES:@STRENGTH

In het geval van IMAP verplichten we TLS weer wél.

Tot slot

Als je je ondertussen afvraagt wat elliptic-curve-cryptografie moge inhouden, is dit artikel goed leesvoer.

Als je alles goed gedaan hebt, zou je een A+ moeten krijgen op SSL Labs.

De hoogst mogelijke score (A+ en 100/100 voor alle categorieën) is alleen haalbaar als je een certificaat met 4096-bits RSA hebt en alleen TLSv1.2 ondersteunt:

Meer info: https://www.ssllabs.com/downloads/SSL_TLS_Deployment_Best_Practices.pdf