TLS verkeer debuggen zonder privésleutel
Een medewerker van een klant vroeg me laatst of het mogelijk is om een package capture (pcap) van een TLS verbinding te decrypten voor debugging en/of troubleshooting doeleinden. Mijn initiële reactie was dat dit alleen mogelijk is wanneer je beschikt over de privésleutel waarmee de TLS verbinding is opgezet. Maar toen ik er wat beter over nadacht, realiseerde ik me dat dit niet meer klopt. “Vroeger” was dit onder bepaalde omstandigheden wel mogelijk, maar bij een moderne TLS verbinding werkt dit niet meer als gevolg van verbeterde protocol eigenschappen.
Als je je wel eens in de gedetailleerde werking van het TLS protocol (of het aanverwante maar verouderde SSL protocol) hebt verdiept, dan weet je dat het er in grote lijnen op neer komt dat asymmetrische cryptografie (ook public/private key cryptografie genoemd) alleen maar wordt gebruikt voor de veilige uitwisseling van een symmetrische sleutel waarmee de sessie vervolgens daadwerkelijk wordt versleuteld. Deze symmetrische sleutel wordt daarom ook wel de sessiesleutel genoemd, en beide partijen (de client en de server) hebben deze sleutel nodig om versleuteld gegevens uit te kunnen wisselen. Maar er is ook een mechanisme waarbij asymmetrische cryptografie niet vereist is om te zorgen dat beide partijen over de sessiesleutel beschikken (maar wel t.b.v. andere doeleinden wordt toegepast). Je kan dus stellen dat er twee mechanismen zijn die er op hun eigen manier voor zorgen dat de client en de server dezelfde sessiesleutel hebben t.b.v. symmetrische versleuteling:
- Key exchange – bij dit mechanisme (gebruikt door de algoritmen RSA en DSA) maakt de client een zogenaamd ‘pre-master secret’ aan waarmee beide partijen een ‘master secret’ creëren. Dit master secret wordt vervolgens gebruikt om de sessiesleutels te creëren waarmee het berichtenverkeer wordt versleuteld. Het pre-master secret moet dus geheim blijven om de vertrouwelijkheid van de sessie te kunnen garanderen. Daarom vindt de uitwisseling ervan plaats met behulp van asymmetrische cryptografie.
- Key generation – wanneer dit mechanisme wordt gebruikt (DH algoritme) creëren de client en de server bij het opzetten van een verbinding verschillende componenten van zowel private als publieke aard. Het publieke component wordt gedeeld met de andere partij, maar het private component blijft geheim en wordt niet gedeeld. Vervolgens voeren beide partijen een aantal slimme berekeningen uit met het publieke component van de ander en het private component van zichzelf. Het resultaat van deze berekeningen wordt gedeeld met de andere partij, waarna er wederom een aantal slimme berekeningen wordt uitgevoerd met het ‘master secret’ tot gevolg. Dit master secret wordt vervolgens gebruikt om sessiesleutels mee te creëren. Het is dus niet nodig om asymmetrische cryptografie toe te passen voor het uitwisselen van een geheim component, omdat het simpelweg niet nodig is dit uit te wisselen.
De meest veilige implementaties maken bij zowel key exchange als key generation gebruik van zogenaamde ‘ephemeral keys‘. Letterlijk betekent dit ‘vluchtige sleutels’, waarmee wordt bedoeld dat eenmalig-te-gebruiken sleutels (‘one-time-use keys’) worden gebruikt. Bij een volgende (toekomstig op te zetten) sessie wordt het hele mechanisme dus opnieuw doorlopen, en worden er nieuwe sleutels gegenereerd. En dan komen we uit bij het belangrijkste verschil tussen deze twee mechanismen.
Key exchange versus key generation
Het grote verschil tussen deze methoden zit hem in het feit dat bij key generation de basis voor de encryptie steeds anders is en er geen geheim is dat uitgewisseld dient te worden, terwijl er in het geval van key exchange altijd een privésleutel aan ten grondslag ligt waarmee een noodzakelijk gedeeld geheim wordt uitgewisseld. Een aanvaller die het volledige netwerkverkeer onderschept (dus inclusief de TLS handshake) heeft in het geval van key generation nooit voldoende componenten tot zijn beschikking om de sessiesleutels te kunnen (her)berekenen. In het geval van key exchange blijf je hiervoor afhankelijk van de privésleutel. Wanneer een aanvaller deze te pakken krijgt, kan hij of zij op basis van het onderschepte netwerkverkeer de gebruikte sessiesleutel uitrekenen (bijvoorbeeld met Wireshark) en dus het berichtenverkeer ontsleutelen.
Het concept/ontwerp wat ten grondslag ligt aan key exchange is dus simpelweg niet in staat in om het gebruik van ‘ephemeral keys’ 100% te borgen. De sessiesleutels zijn wel steeds anders, maar zijn altijd gelinkt aan een ‘pre-master secret’ dat met behulp van een privésleutel (asymmetrische encryptie) is uitgewisseld. Key exchange gaat dus goed zolang je kunt garanderen dat de privésleutel geheim blijft. Maar een privésleutel kan gestolen worden, of kan worden gekraakt/geraden als gevolg van nieuw ontdekte kwetsbaarheden of door een enorme toename in rekenkracht. Dus wanneer een aanvaller in het verleden in staat is geweest versleuteld berichtenverkeer te onderscheppen, en pas 10 jaar later in staat is om de privésleutel uit te rekenen, kan deze alsnog het onderschepte verkeer ontsleutelen.
Bij key generation speelt dit dus niet omdat er geen geheime componenten worden uitgewisseld. Het gebruik van het Diffie-Hellman (DH) mechanisme in combinatie met het gebruik van ‘emphemeral keys’, wordt daarom Perfect Forward Secrecy (PFS) genoemd. Het kan in de toekomst nog steeds mogelijk zijn om een bepaalde sessiesleutel te kraken, maar de impact hiervan blijft dan beperkt tot de specifieke sessie waarbinnen deze sessiesleutel is gebruikt. Er is dus geen gekraakt component dat met terugwerkende kracht kan worden toegepast om ook ander (ouder) onderschept berichtenverkeer te ontsleutelen. Wil je een andere sessie ontsleutelen, dan zul je een andere sessiesleutel moeten kraken.
TLS debuggen ondanks perfect forward secrecy
Dan nu terug naar de TLS debug behoefte. Het is nu duidelijk dat het hebben van een privésleutel alleen maar nut heeft wanneer er gebruik is gemaakt van een key exchange mechanisme. In situaties waarbij er gebruik is gemaakt van key generation (DH) zul je anders te werk moeten gaan. Moderne browsers zoals Mozilla Firefox en Google Chrome maken gebruik van een set libraries genaamd Network Security Services (NSS) die onder andere het gebruik van SSL/TLS regelt. Het mooie is dat NSS ook voorziet in een Key Logging functie. Door dit te gebruiken schrijft een browser de gebruikte sessiesleutels weg naar een logbestand. En deze kun je in Wireshark gebruiken om berichtenverkeer (op basis van key generation) te ontsleutelen.
Om de key log functie in te schakelen, hoef je alleen maar een environment variabele in je besturingssysteem in te stellen. Dit kan onder Linux, Mac OS X en onder Windows. In Windows 10 gaat dit bijvoorbeeld als volgt: Instellingen > Systeem > Info > Systeeminfo > Geavanceerde systeeminstellingen > Tabblad geavanceerd > Omgevingsvariabelen. In dit scherm voeg je een nieuwe variabele toe met de naam “SSLKEYLOGFILE” waarbij de waarde de locatie en bestandsnaam van het logbestand bevat. Bijvoorbeeld “e:\sslkeylogfile.log” zoals ook te zien in het onderstaande screenshot.
Wanneer je hierna je browser opstart, gaat de rest vanzelf en wordt het desbetreffende bestand gevuld met sessiesleutels. Omdat dit alleen werkt voor browsers, is het niet zomaar mogelijk om sessiesleutels vanuit andere applicaties te loggen. Ergens begrijp ook wel dat dit geen standaard optie in het OS is, want daarvan zie ik ook wel de risico’s. Wel stuitte ik op een Java library genaamd jSSLKeyLog die het mogelijk maakt om sessiesleutels van Java applicaties te loggen. Ken jij nog meer mogelijkheden om sessiesleutels te loggen? Laat dan even een reactie achter. Happy TLS debugging.
Afbeelding van Cyberstreams.
Plaats een Reactie
Meepraten?Draag gerust bij!