Toto je přesně věc, kterou probíráme na kurzu GOC173 - Enteprise PKI v GOPASu!
V poslední době sleduju na různých místech výskyt různých článků o PFS (perfect forward secrecy, nebo i jenom FS - forward secrecy) v TLS/SSL protokolu (nadále tomu budu říkat pouze TLS, protože SSL už dneska používáte jen nějakých nekompatibilních případech). Vzhledem k tomu, že to je plné různých fám, podívejme se na to i my.
Autentizační a přenosové klíče
PFS je obecný kryptografický termín, který znamená v podstatě následující - velmi zjednodušeně. Řekněme, že komunikujeme zašifrovaně. K tomu nejspíš potřebujete dva šifrovací klíče. Jeden klíč bude autentizační (authentication key) a druhý bude přenosový (session key).
Autentizačním klíčem (klíči) (authentication keys) si obě strany přenosu vzájemně prokazují identitu. Přenosovým klíčem (session key) šifrují přenášená data. Přenosové klíče se budou nejspíš generovat nějak náhodně, obvykle opakovaně i v průběhu přenosu (re-keying), například po několika minutách, nebo po nějakém objemu přenesených dat. Zatímco ty autentizační budou asi mnohem trvalejší, protože obě strany je musí buď sdílet - v případě symetrických algoritmů, nebo jim musí věřit - v přípravě kryptografie asymetrické.
Pro TLS se používá jako autentizační klíč běžný serverový (server authentication) certifikát s veřejným klíčem (public key) a jemu odpovídající soukromý klíč (private key). Přenosové klíče se generují náhodně.
Jak jste asi zažili, vygenerovat si, nebo koupit certifikát není moc jednoduché a budete ho tedy používat poměrně dlouhou dobu, obvykle rok až dva (tak jak si přeje standard NIST algorithm advisory). Takže ten autentizační klíč bude opravdu na dlouhou dobu.
Tyto dva klíče ovšem budou mít nějakou vazbu - abychom svázali přenosový klíč s ověřením identity, tedy abychom autentizovali přenos přenosového klíč. Prakticky jsou dvě možnosti - buď děláte key exchange, nebo key agreement:
- key exchange - znamená, že klient dostane od serveru jeho autentizační veřejný klíč jako součást certifikátu. Klient si vygeneruje (náhodně) přenosový klíč a zašifruje ho veřejným klíčem serveru. A takto chráněný ho pošle zpět na server. Server si to dešifruje svým privátním klíčem a oba tak znají přenosový klíč, kterým dále šifrují. TLS k tomuhle používá RSA key exchange algoritmy. Klíč se musí přenést tajně.
- key agreement - to jsou modifikace Diffie-Hellman key agreement algoritmu. Při D-H se kousky přenosového klíče přenáší totálně nezašifrovaně. To by ale bylo náchylné na MITM (man in the middle) útok. Takže ty kousky přenosového klíče jsou podepsány soukromým klíčem serveru a naopak veřejným klíčem serveru při cestě z klienta. Ano, veřejným klíčem se skutečně spíše "šifruje" než "podepisuje", ale schválně tu píšu "podepisuje", protože nejde o tajný přenos, jako spíš o podpis - nehledě na to, že tyto dvě operace jsou technicky stejné.
Poznámka - RSA key exchange tedy šifruje přenosový klíč, zatímco D-H key agreement ten klíč jen podepisuje. Z toho taky plyne použití, které musíte mít v certifikátu - Key Usage - buď Key encipherment pro RSA key exchange, nebo Digital signature pro DH key agreement.
PFS - perfect forward secrecy
Pokud máme PFS, znamená to, že bezpečnost klíče přenosového nezávisí na bezpečnosti klíče autentizačního. Tedy šifrovací klíč pro přenos se musí generovat nezávisle na privátním klíči autentizačního certifikátu.
RSA šifruje přenosový klíč privátním, takže RSA nemá PFS. Zatímco DH a ECDH přenosový klíč pouze podepisuje, takže D-H a EC-DH naopak PFS mají. Detaily dále:
Bezpečnost v obou případech, jak key exchange, tak i key agreement, stojí na ochraně autentizačního klíče. Pokud ho má jen server bezpečně uložený, tak je všechno v pořádku. Od toho se to také jmenuje soukromý klíč (private key). Ale teď rozdíl.
Certifikáty mají přece nějakou platnost (time validity). Platnost certifikátu vyjadřuje, po jakou dobu musí vlastník klíče (subject) dbát o bezpečnost soukromého klíče v případě podpisu (digital signature) nebo key agreement (viz. i něco o časových razítkách). Jakmile platnost certifikátu skončí, můžete ho "politicky" vyhodit na internet, nebo nechat povalovat na flešce, spolu s privátním klíčem a nikdo vám nemůže nic říct. (To je stejné jako v případě občanky, neplatná občanka se může povalovat kde chce, už si na ni nic nepůjčíte, ani děcka ze školky nevyzvednete :-))
Pokud se jedná o šifrovací certifikát (key encipherment, data encipherment), tak byste tohle udělat neměli. Možná jsou ještě nějaká data zašifrována vaším veřejným klíčem a privátní (soukromý) klíč by to všechno dešifroval. Příklad jsou S/MIME maily, nebo EFS soubory.
A to je ten kámen úrazu. TLS je jenom přenosové šifrování. Přenosové klíče se používají jen chvilku a potom "z drátů zmizí". Jenže. Co když ten přenos někdo nachytal. A schoval si ho na lepší časy. Dokud je váš privátní klíč pro key exchange v bezpečí, dešifrovat se to nedá. Ale co když se vám ten klíč ztratí někdy později. Nebo se na něho vykašlete po vypršení jeho platnosti - byť byste to udělat neměli.
Pro NSA a jiné hackery může být mnohdy zajímavé prostě chytat zašifrované TLS a jenom si to někde uložit. A počkat si, jestli časem nedostaneme ten certifikát. Identifikace půjde udělat krásně automaticky. Jak agenti po světě zasílají nalezené privátní klíče, tak se v historii otevírají nevídaná data.
Pokud děláte key encipherment (tedy třeba právě TLS RSA key exchange, nebo i PPTP VPN), tak jste náchylní na tento druh útoku - nazval bych to "opožděná krádež klíče".
Naopak, pokud používáte key agreement (tedy u TLS D/H key agreement, nebo jeho eliptická obdoba ECDH key agreement), tak tohle nenastane. Přenášené části klíče jsou z podstaty veřejné. Podepisujete je privátním klíčem, tahle signatura se dá kdykoliv v budoucnu stejně ověřit veřejným klíčem, ale hlavně její zlá pozdější modifikace už nemá smysl.
TLS suites ve Windows a v internetu a PFS
TLS se domlouvá na šifrovacích algoritmech v okamžiku, kdy se začíná spojení se serverem. Klient pošle na server seznam algoritmů (s pořadím preference) - přesněji řečeno skupin (suite) algoritmů - které umí, a server si z nich jeden vybere a tím se domluví. Takže to vždycky stojí na schopnostech klienta a serveru, ale také na pořadí, v jakém jsou ty sujty posílány na server. V jakém jsou pořadí na klientovi!
Například Windows XP a jejich TLS knihovna Schannel ovládají pouze protokol TLS 1.0 a umí jen následující sujty v tomto výchozím pořadí:
TLS_RSA_WITH_RC4_128_MD5
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_DES_CBC_SHA
TLS_DHE_DSS_WITH_DES_CBC_SHA
TLS_RSA_EXPORT1024_WITH_RC4_56_SHA
TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA
TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA
TLS_RSA_EXPORT_WITH_RC4_40_MD5
TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
TLS_RSA_WITH_NULL_MD5
TLS_RSA_WITH_NULL_SHA
Jak si můžete všimnout, není tam ani jeden AES, není tam ani jedna SHA256 (SHA2 obecně), není tam žádný ECDH. Je tam sice DH algoritmus, ale jen v případě, že na serveru je DSS (DSA) certifikát. Normální web serverové certifikáty jsou RSA, nikoliv DSA. Takže můžeme říci, že z Windows XP klienta žádné PFS v TLS nemáte.
Windows Server 2003 přidal podporu AES šifrování. To je ale pro PFS totálně nepodstatné. Takže zase smůla:
TLS_RSA_WITH_AES_128_CBC_SHA AES128-SHA
TLS_RSA_WITH_AES_256_CBC_SHA AES256-SHA
Až na Windows 7 a Windows 2008 (ano, je to i na Vista ale kdo tohle dneska má, že :-)) přišlo i do TLS 1.0 už ECDH: - stejná situace je i na Windows 8, Windows 8.1 a Windows 2012 i Windows 2012 R2:
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_RC4_128_MD5
Jsou tam dvě suitey ECDH+RSA, což je provozovatelné s běžnými web serverovými certifikáty (narozdíl od ECDH+ECDSA, protože eliptické ECDSA certifikáty nikdo nemá). Ale všimněte si, že nejsou na prvních místech. Klient tedy preferuje spíše klasický RSA key exchange který nemá PFS. Místo aby preferoval ECDH, kde je PFS samosebou.
Jak to pořešit? Museli byste buď na klientovi, nebo na serveru, vypnout ty hornější suity. Buď se to udělá v registrech, nebo přes Group Policy (GPO). Jenže se vystavujete nekompatibilitě. Co když to nějaký server, nebo klient, nebude umět, že?
Poznamejme ještě bokem, že TLS 1.0 ani na Windows 8.1 neumí SHA256 (obecně SHA-2) - opět to nemá co do činění s PFS, proto jen poznámečka kvůli kompletnosti. Takové sujty jsou až pro TLS 1.1 a TLS 1.2, které se také musí explicitně zapnout, a to i na Windows 2012 R2:
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_128_CBC_SHA
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA
TLS_RSA_WITH_RC4_128_SHA
TLS_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P256
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA_P384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA384_P384
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA_P384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA_P384
TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
TLS_DHE_DSS_WITH_AES_128_CBC_SHA
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
TLS_DHE_DSS_WITH_AES_256_CBC_SHA
TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
TLS_RSA_WITH_RC4_128_MD5
SSL_CK_RC4_128_WITH_MD5
SSL_CK_DES_192_EDE3_CBC_WITH_MD5
TLS_RSA_WITH_NULL_SHA256
TLS_RSA_WITH_NULL_SHA
Kde zjistím, jak je na tom můj server?
Pokud se váš server dívá do internetu, tak si ho můžete nechat otestovat z pohodlí domova například na adrese www.ssllabs.com. Stačí zadat adresu vašeho serveru. Nebo se můžete podívat, jak jsou na tom cizí web servery, jako například gmail, nebo microsoft.
Tak to je pro dnešek všechno, milé děti. Tak do hajan :-)