Transport Layer Security (TLS), de opvolger van Secure Sockets Layer (SSL) zijn de protocollen die gebruikt worden om o.a. https-verbindingen te realiseren. De versies SSL versie 1 t/m 3 zijn al sinds 1994 in ontwikkeling. TLS versie 1.0, uitgebracht in 1999, voegt qua veiligheid niet veel toe gezien deze sterk overeenkomt met SSL 3.0 (werd intern ook wel SSL 3.1 genoemd). Pas in 2006 werd deze opgevolgd door versie 1.1 en sinds 2008 is versie 1.2 beschikbaar.

Doordat de ontwikkeling erg lang is blijven steken op SSL, worden deze protocollen in de meeste webservers nog steeds ondersteund. In Apache2.2 is SSLv3 standaard ingeschakeld en pas in Apache2.4 staat deze standaard uit, maar wordt deze nog wel ondersteund (inderdaad je kunt 'm gewoon weer aanzetten!) (niet doen dus!).

Gelukkig neemt de ondersteuning voor SSLv2 en SSLv3 sterk af, maar wordt TLSv1.0 door bijna 100% van alle sites ondersteund. Alle reden om aan te nemen dat ook jouw 'veilige' https-website net zo onveilig kan zijn als een platte http-website.

SSL/TLS testen op kwetsbaarheden

De gemakkelijkste methode is de SSL Server test van Qualys, deze geeft je een duidelijk overzicht van de meeste kwetsbaarheden (als je onderstaande instructies opvolgt krijg je een A+!). Wanneer je de gelukkige eigenaar bent van een Linux bakkie, geeft testssl.sh je dezelfde testresultaten (deze verdient mijn voorkeur omdat deze iets meer details geeft).

Natuurlijk is het zaak dat je, voordat je begint, wel een werkend SSL certificaat op het betreffende domein of de betreffende verbinding hebt geïnstalleerd.

SSL is stuk, schakel SSLv3 uit!

In oktober 2014 werd de "POODLE" issue vrijgegeven, een man-in-the-middle-attack die een gigantisch lek in alle versies van SSL aan het licht bracht. Ook al is de hack technisch zeer lastig uit te voeren, voor Michele Spagnuolo was het voldoende reden om een website op te richten met instructies hoe je SSLv3 uitschakelt

SSLv3 testen

Volgens deze instructies kan dit het gemakkelijkst via het openssl commando:

echo | openssl s_client -connect domain.tld:443 -ssl3

Wanneer deze opdracht No peer certificate available, Secure connection IS NOT supported of iets dergelijks retourneert, weet je dat SSLv3 niet beschikbaar is. Komt er een lap andere meldingen, inclusief een certificaat terug in het resultaat dan staat SSLv3 aan en heb je wat te doen.

SSLv3 uitschakelen in Apache

De instructies voor de webserver, Apache2.2 en Apache2.4 zijn hetzelfde. Open het bestand /etc/apache2/mods-enabled/ssl.conf en pas de regel beginnend met SSLProtocol als volgt aan:

SSLProtocol -all +TLSv1.2

Hiermee schakel je alle protocollen uit, behalve TLSv1.2. Vervolgens voer je de configtest uit en als hier geen resultaten op terugkomen kun je Apache herstarten:

apachectl configtest
apachectl graceful

Key Exchange Strength / RSA-keysize

De RSA-key is de sleutel die gebruikt wordt om het verkeer te versleutelen en weer uit te pakken aan de server kant. Je kunt deze key het beste zien als een wachtwoord waarbij de mate van beveiliging toeneemt als het wachtwoord ingewikkelder (langer) wordt. De lengte van deze key wordt ookwel Strength of Keysize genoemd en bepaalt de Exchange Strength, hoe krachtig de uitwisseling beveiligd is.

Bij het aanvragen van een certificaat geef je de key size op. De lengte van de public-key wordt hierbij gelijkgesteld aan de lengte van de private-key. Hoe hoger hoe beter, maar momenteel adviseren wij 4096 bits.

Key Size testen

Door een verbinding op te zetten via de openssl tool kan de huidige key-size worden opgehaald:

echo | openssl s_client -connect domain.tld:443 | grep 'public key'

In het resultaat zou "Server public key is 4096 bit" moeten terugkomen, alles dat minder is is daarmee ook minder veilig.

Key size specifieren bij OpenSSL genrsa

Bij het aanvragen van een nieuw certificaat kan de rsa-key size als volgt worden gedefinieerd:

openssl req -new -newkey rsa:4096 -keyout domain.tld.key -out domain.tld.csr

Key size specificeren bij aanvragen Let's Encrypt certificaat

De key size specificeren in certbot van Let's Encrypt kan tijdens het aanvraagproces (als je al een certificaat hebt aangevraagd zal de tool je vragen of je het certificaat wilt vervangen):

certbot certonly --apache --rsa-key-size 4096 --domains domain.tld

Perfect Forward Secrecy (PFS)

De versleuteling van SSL is veilig doordat een geheim deel, de private-key of RSA-key, wordt gebruikt om het versleutelde verkeer van de client naar de server weer terug te brengen naar leesbare data (decryption). Dat betekent dat alle verkeer tussen elke client en de server ontsleuteld kan worden als deze private-key uitlekt, kortom dit is een single-point-of-failure.

Om dit op te lossen is Perfect Forward Secrecy of PFS bedacht, waarbij niet de standaard private-key wordt gebruikt, maar een key die uniek is voor elke sessie[1]. Deze unieke session-key of Diffie-Hellman Ephemeral wordt in combinatie met de private-key gebruikt om het verkeer terug te sleutelen naar leesbare tekst. Het voordeel is dat verkeer dat is uitgelezen door man-in-the-middle-attacks alsnog niet uit te lezen is, het nadeel is dat deze extra encryption-layer meer processorkracht vereist. Tevens wordt deze versleuteling door verouderde browsers (Internet Explorer <= 8) niet wordt ondersteund.

Het advies is alsnog om PFS te implementeren en zeker geen uitzonderingen voor oudere browsers te maken, tenzij je natuurlijk onvoldoende processorkracht beschikbaar hebt (da's volgens mij alleen als je je website vanaf een Raspberry draait…)

Perfect Forward Secrecy testen

Met de openssl-client (versie >= 1.0.2) kun je controleren of een verbinding PFS ondersteund, gebruik hiervoor onderstaande opdracht:

echo | openssl s_client -connect domain.tld:443 -cipher "EDH" | grep -i "Server .* key"

Deze opdracht zou o.a. "Server Temp Key: DH, 4096 bits" moeten retourneren. Komt hier 1024 bits of geen resultaat uit, dan is PFS niet juist ingesteld.

Perfect Forward Secrecy inschakelen in Apache

Volgens de instructies[2] op bettercrypto.org kun je de volgende regels toevoegen aan /etc/apache2/mods-enabled/ssl.conf (of pas bestaande regels aan):

SSLHonorCipherOrder On
SSLCipherSuite "EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA"

Eventueel kun je deze aanpassingen ook maken in jouw Virtualhost, mocht je daar gebruik van maken.

Certification Authority Authorization (CAA)

Omdat iedereen een certificaat kan aanvragen voor elk willekeurig domein, zijn uitgevers van certificaten — Certificate Authorities (CAs) — verplicht om te verifiëren dat de aanvrager daadwerkelijk eigenaar van het betreffende domein is. Dit gebeurt d.m.v. Technische Verificatie, waarbij er bijvoorbeeld op een link geklikt moet worden die via de mail wordt toegestuurd, een DNS-record moet worden toegevoegd of dat er op papier bewijs wordt geleverd van eigendom.

Door middel van een CAA DNS-record geef jij aan van welke CA(s) jij certificaten in gebruik hebt[3]. Wordt er via jouw service een certificaat geleverd, welke niet is uitgegeven door een van de gegeven CA's, dan wordt het certificaat niet vertrouwd. Als het een kwaadwillend persoon lukt om, ondanks de technische verificatie, namens jou een certificaat aan te vragen, zorgt CAA ervoor dat dit certificaat door de cliënt (browser) alsnog geweigerd kan worden.

Certification Authority Authorization instellen

Om CAA te configureren dient er een DNS-record toegevoegd te worden. Gebruik eventueel de tool van SSLMate voor de juiste syntax. Voor letsencrypt kun je de volgende BIND-configuratie gebruiken:

domain.tld.	IN	CAA	0 issue "letsencrypt.org"
domain.tld. IN CAA 0 issuewild ";"

Wanneer je de CA ook voor subdomeinen wilt toestaan, laat je het tweede DNS-record met "issuewild" weg.

Certification Authority Authorization testen

Het testen van CAA kan relatief gemakkelijk via dig:

dig +short CAA domain.tld

HTTP Strict Transport Security (HSTS)

Het https-protocol bestaat heel simplistisch gezien uit een standaard http-protocol aangevuld met SSL/TLS versleuteling. Bij een protocol-downgrade-attack (bijvoorbeeld Cipher Suite Rollback Attack) forceert de cliënt een minder veilige verbinding waardoor de server de data minder veilig over het netwerk verstuurd. Door HSTS toe te passen forceer je een veilige https verbinding, in alle andere gevallen wordt de verbinding geweigerd.

De werking van HSTS testen

HSTS is technisch gezien weinig meer dan een header die door de browser wordt gelezen. Deze header kun je via de curl-tool opvragen[4]:

curl -s -D- https://domain.tld | grep Strict-Transport-Security

Geeft deze opdracht geen resultaat, dan wordt HSTS niet ondersteund.

HSTS instellen in Apache

Voor Apache2.2 en Apache2.4 geldt dat je deze header geforceerd kunt toevoegen aan je virtualhost:

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

Conclusie

Waar SSL ooit werd ontwikkeld om veilig data te versturen tussen cliënt en server en vice-versa, is de techniek intussen sterk achterhaald. Met de opkomst van TLS (vooral TLS1.2) is er een flinke verbeterslag gemaakt die het een aanvaller al een stuk lastiger maakt om gevoelige data te ontfutselen. Lastiger, het is zeer waarschijnlijk een kwestie van tijd voordat ook TLS1.2 het label 'onveilig' zal ontvangen.

Het grootste nadeel is dat deze techniek bijna alle internetverkeer versleutelt (niet alleen https, maar ook mailverkeer, bankmutaties, etc.). Één single-point-of-entrance die de aandacht heeft van de meest geoefende scriptkiddies, want als het ze lukt om een lek te vinden, valt er meteen veel te halen. Dat betekent dat deze techniek zich zal blijven ontwikkelen (hopelijk snel genoeg) en dat je jezelf continu op de hoogte moet houden om ze voor te blijven.

Bronnen

  1. Perfect Forward Secrecy
    https://www.sslcertificaten.nl/support/Terminologie/Perfect_Forward_Secrecy
  2. Paper "Applied Crypto Hardening" (PDF)
    https://bettercrypto.org/static/applied-crypto-hardening.pdf
  3. RFC6844 "DNS Certificate Authority Authorization (CAA) Resource Record"
    https://tools.ietf.org/html/rfc6844
  4. Test HTTP Strict Transport Security
    https://www.owasp.org/index.php/Test_HTTP_Strict_Transport_Security_(OTG-CONFIG-007)