Feilsøking av TLS

Feilsøking av TLS

Vi har tidligere anbefalt å begrense hvilke "cipher suites" og TLS-utvidelser man bruker for å sikre at TLS brukes på en sikker måte. Imidlertid vil man kunne erfare at disse anbefalingene gjør at tjenester slutter å virke på grunn av servere som ikke er satt opp med støtte for de mest moderne variantene av TLS. 

Her skal vi gå gjennom hvordan vi kan feilsøke slike situasjoner med wireshark.

Oversikt over TLS nettverksprotokoll og pakkeformat

For en god gjennomgang av pakkeformatet til TLS er wikipedia en grei referanse, men for alle detaljer kan man gå til kilden, RFC-5246. Nedenfor er en kort oppsummering som grunnlag for den videre diskusjonen.

TLS innebærer at "records" sendes frem og tilbake mellom klient og tjener over en TCP-forbindelse. Hver record har følgende format:

  • Type (1 byte)
  • Versjon (2 bytes)
  • Lengde (2 bytes)
  • Melding, potensielt etterfulgt av en MAC (message authentication) og padding (for block ciphers)

Type kan være en av:

  • Change cipher spec, alle påfølgende records blir kryptert ihht sist avtalte spesifikasjoner
  • Alert, feilmelding
  • Handshake, autentisering og avtale av algoritmer som skal brukes for kryptering
  • Application data
  • Heartbeat

Oppsett av TLS-forbindelsen gjøres i grove trekk med følgende meldinger:

  • Klient -> tjener: oversikt over hvike parametre og utvidelser som støttes
  • Tjener -> klient: valg av cipher suite, sertifikat, nøkkelutveksling mm
  • Klient -> tjener: fortsettelse av nøkkelutveksling, evt klientsertifikat
  • Klient -> tjener: change cipher spec
  • Finish-meldinger i begge retninger

Med passive mekanismer som overvåker nettverkstrafikker er vi bare i stand til å feilsøke meldinger som sendes frem til "change cipher spec". Etter dette vil alle meldinger være kryptert. Men det er ganske mye informasjon som sendes før dette, og nedenfor går vi gjennom de viktigste punktene.

Den fulle handshake-protokollen med alle mulige meldinger er dokumentert i RFC-5246 og ser slik ut:
Client                                            Server
ClientHello               -------->               
                                                  ServerHello
                                                  Certificate*
                                                  ServerKeyExchange*
                                                  CertificateRequest*
                          <--------               ServerHelloDone
Certificate*
ClientKeyExchange
CertificateVerify*
[ChangeCipherSpec]
Finished                  -------->
                                                  [ChangeCipherSpec]
                          <--------               Finished
Application Data          <------->               Application Data

(meldinger merket med * er valgfrie og avhengig av hvilke parametre som er valgt).

Oversikt over en TLS-handshake i wireshark

For dette formålet er det bare "handshake"-meldinger vi er interessert i, og sannsynligvis bare kommunikasjon mot en bestemt IP-adresse. Det er derfor lurt å starte med et filter slik at vi bare ser de aktuelle meldingene, her kan vi bruke "ssh.handshake && ip.addr == <ip>" som gjør at vi bare ser "handshake"-meldinger til eller fra angitt ip-adresse:

ssl.handshake

Her ser vi at det er tre ulike "client hello"-meldinger, altså har klienten satt opp tre TLS-forbindelser mot serveren. For å skille disse fra hverandre kan det være en god ide å legge til kolonner for "source port" (høyreklikk på overskriften, velg "column preferences").

Client Hello

Dette er hvor klienten forteller hva den støtter. I wireshark ser den for eksempel ut som dette:

Wireshark

Med bakgrunn i tidligere anbefalinger om TLS-konfigurasjon er dette de mest relevante punktene å se etter:

Version

Dette er den høyeste versjonen klienten støtter. Denne sier ikke noe om hvilke andre versjoner som evt er støttet, slik at dersom serveren bare støtter lavere versjoner som ikke er støttet av klienten vil dette stoppe senere i protokollen. Legg merke til at det finnes til versjons-felt i denne meldingen:

  • Versjonsfeltet på record-nivå er versjonen for den record som er sendt
  • Versjonsfeltet inne i Client Hello sier hvilken versjon klienten ønsker å bruke

I praksis vil disse alltid være like, men man kan teoretisk tenke seg tilfeller av at klienten ønsker å reforhandle tls-parametre og skifte til en annen versjon enn den som brukes for øyeblikket.

Cipher Suites

Er listen av cipher suites klienten sier den støtter, i prioritert rekkefølge.

Chiper Suites

Hvis serveren ikke støtter noen av disse vil den feile, men den nederste (TLS_RSA_WITH_AES_128_CBC_SHA) er påkrevet i TLS 1.2-standarden så vi kan regne med at en TLS 1.2-server støtter denne. I tidligere TLS-versjoner er det dog en annen cipher suites som er definert som påkrevet, så det kan være noen grensetilfeller hvor noe potensielt ikke virker.

Signeringsalgoritmer

Videre ser vi extension "signature_algorithms" som lister hvilke signatur-algoritmer klienten støtter:

Signature algorithms

Denne brukes to steder:

  • Serveren autentiserer seg ved å signere ServerKeyExchange-meldingen
  • Serveren sitt sertifikat er signert av en CA

Feltet signature_algorithms fra klienten forteller hva den aksepterer fra serveren i disse to tilfellene. Når det gjelder sertifikat kan man se for seg at serveren har flere ulike sertifikat og velger ett med en kompatibel signeringsalgoritme, men i praksis vil serveren bare ha ett relevant sertifikat, og det var CA som bestemte hvilken algoritme som ble brukt til signering av dette. Dersom klienten ikke støtter signeringsalgoritmen valgt av CA vil autentiseringen feile.

Andre interessante felt i Client Hello

Av andre ting man kan se etter har vi:

  • Compression Method: hvis denne inneholder et element og dette er null betyr det at komprimering ikke er støttet
  • Extension server_name: sier hvilket DNS-navn klienten forsøker å koble seg til, dette er spesielt relevant ved virtual hosting. (Kalles også SNI: server name indication)
  • Extension renegotiation_info: sier at utvidelsen med sikker renegotiation av forbindelsen er støttet.

Server Hello

Serveren svarer på en Client Hello med en tilsvarende Server Hello. Denne ser slik ut:

Server Hello

Her kan vi legge merke til følgende:

  • Version: serveren har valgt en TLS-versjon som er mindre eller lik den klienten foreslår.
  • Cipher Suite: serveren har valgt cipher suite. Her ser vi at dette var ikke den som var øverst prioritert hos klienten, som kan skyldes at den høyest prioriterte ikke er støttet av serveren, eller at serveren av andre grunner har overstyrt klientens prioritering.
  • Extension renegotiation_info sier at serveren også støtter "secure renegotiation"

Resten av handshake

Videre ser vi meldinger fra serveren:

Handshake server

Og fra klienten

Handshake Klient

Etter dette er all videre kommunikasjon fra klienten kryptert.
Fra serveren kommer en "session ticket" som gjør at klient og server kan fortsette kommunikasjonen senere med en cache av krypteringsparametre, slik at de slipper å gjøre en full handshake på nytt, men etter dette er også all serverkommunikasjon kryptert.

Hva kan gå galt?

Dersom serveren foreslår en protokollversjon som klienten ikke støtter (vil typisk skje dersom klienten kun støtter 1.2 mens serveren kun støtter eldre enn 1.2) vil klienten avbryte forbindelsen med en "alert":

Alert


Dersom klienten foreslår en eldre protokollversjon enn serveren støtter vil serveren tilsvarende svare med en alert, men det kan også hende den bare terminerer forbindelsen. Dette ser typisk ut som følgende: Client Hello blir etterfulgt av TCP FIN, potensielt også TCP RST:

TCP

Dersom serveren ikke støtter noen av de cipher suites klienten foreslår, vil den svare med Alert: handshake_failure

comments powered by Disqus