Root cause analysis: storing met eID ontcijferd

Steeds meer gebruikers rapporteren dat het niet meer mogelijk is om in te loggen via eID met Chrome. Jeffrey ontcijfert de storing.

Steeds meer gebruikers rapporteren dat het niet meer mogelijk is om in te loggen via eID met Chrome. In eerste instantie niet reproduceerbaar maar na herstarten van de browser (en een update van 81 naar 83) is het probleem reproduceerbaar. Authenticatie lijkt te lukken tot en met pin ingeven, maar daarna verschijnt een connection reset error. Het probleem doet zich niet voor op CSAM.

Op onderzoek uit

Voor we nog maar kunnen denken aan een oplossing, moeten we eerst achterhalen wat er precies foutloopt. Een aantal zaken die nog wel eens voor problemen kunnen zorgen, kunnen we a priori al elimineren. Het probleem kan niet aan de kaart liggen en niet aan de middleware.

De browser zelf is een geval apart. Waarom lukt het inloggen met Chrome op CSAM wel en niet op MyAccount (het authencitcatiesysteem achter al onze applicaties)? En waarom is er enkel een probleem met Chrome? Inloggen lukt namelijk nog steeds met Firefox, Edge en Internet Explorer.

Op het eerste zicht werken CSAM en MyAccount op dezelfde manier. Je komt op een https-beveiligde site en pas na het klikken op een link wordt het certificaat van de eID-kaart opgevraagd. Dit lijkt een dood spoor.

Het opvragen van het client certificaat wordt getriggerd door een aparte TLS-configuratie voor dat stuk van de website. Toch maar eens de configuratie bekijken die ervoor moet zorgen dat het certificaat opgevraagd wordt. Na een aantal zaken eerder willekeurig uit te proberen moeten we vaststellen dat we ook daar op een dood spoor zitten.

Dan toch maar de siteconfiguratie bekijken

Via netsh http show sslcert kan je per ip adress+port de TLS configuratie bekijken. Alles ziet er correct uit maar één detail valt op: 'Negotiate client certificate' staat op 'Disabled'. Op zich is dat niet zo vreemd, want we vragen inderdaad pas het client certificate op eens de gebruiker doorklikt op aanmelden met eID.

Onder het motto 'minder werken kan het niet' toch eens 'Negotiate client certificate' aan zetten.

Wanneer we nu naar MyAccount navigeren, krijgen we onmiddellijk het certificaat-keuzescherm. En bingo! Na het ingeven van de pincode lukt het om in te loggen met Chrome. Uiteraard is dit geen oplossing, want nu zou ten allen tijde via eID ingelogd moeten worden.

Maar waarom werkt dit wel? Er komt duidelijk een punt waarop de server de client om een certificaat vraagt en de client dat certificaat doorstuurt. Door 'Negotiate client certificate' op siteniveau te activeren, gebeurt dit onmiddellijk bij het openen van de TLS-verbinding. Onder normale omstandigheden gebeurt dit pas later, nadat de TLS-verbinding reeds gelegd is.

Al snel belanden we op het concept 'TLS renegotiation': dit laat de zowel de client als de server toe om de karakteristieken van de bestaande TLS-verbinding te wijzigen. Eén van de parameters die daarbij gewijzigd kan worden is of de client zich moet identificeren via een certificate.

Als het onmiddellijk opvragen van het client certificate wel werkt en het via renegotiation niet werkt, dan hebben we een aanknopingspunt.

Maar waarom werkt dat dan wel bij CSAM?

Enig speurwerk later maakt alvast dat deel duidelijk: CSAM werkt niet met renegotiation! Wanneer de gebruiker op de eID knop klikt dan wordt deze afgeleid naar een aparte server met een eigen IP-adres en wordt er dus een nieuwe TLS-verbinding opgebouwd; deze keer met de vereiste dat ook de client een certificate presenteert.

We lijken op het juiste spoor te zitten maar veel meer dan een generieke 'handshake failed' melding in de 'Failed Request Logging' van IIS vinden we niet terug. Dat er iets foutloopt met de handshake kunnen we na het activeren van de logging van schannel bevestigen.

Error code 40 vinden we in de RFC (https://tools.ietf.org/html/rfc8446) inderdaad terug als een 'handshake failure'.

Wanneer we via Wireshark het verkeer tussen client en server proberen te traceren, stoten we al snel op het probleem dat alles na de initiële TLS handshake (uiteraard) encrypted is. We zien met andere woorden niets van de renegotiation aangezien die gebeurt op een moment dat de verbinding reeds encrypted is.

Gelukkig vinden we na wat Googlefu ook hier een oplossing voor. Zowel Chrome als Firefox ondersteunen het exporteren van het nodige keymateriaal zodat Wireshark het TLS-verkeer kan decrypten. Dit kan door het configureren van de 'SSLKEYLOGFILE' environment variabele. Eens die geconfigureerd is, schrijven de browsers de nodige key informatie weg bij het opzetten van de TLS-verbinding. Wireshark op zijn beurt gebruikt de gelogde key informatie om de encrypted packets terug te decrypten. Nu de TLS data decrypted werden kon de zoektocht verder gaan.

Al snel werd er een verschil gevonden tussen Chrome 81/FF/... en Chrome 83. Chrome 83 stuurde het signature rsa_pcks1_sha1 niet meer door als mogelijk signature algoritme.Wanneer we nu een successvolle trace vergeleken met een falende trace, bleek dat bij de succesvolle trace net dit specifiek signature algoritme initieel genegotieerd werd door de server. Waar bij Chrome 83 een recentere variant van dit algoritme genegotieerd werd, nl rsa_pcks1_sha256.

De eID kaart ondersteunt een aantal protocollen maar op rsa_pcks1_sha1 na, wordt geen enkel protocol meer ondersteund in TLS 1.3. Blijkbaar werd deze case niet correct afgehandeld door Windows want ondanks het feit dat de handshake succesvol genegotieerd werd, sloot de server daarna toch de verbinding af.

Eens op dit punt gekomen was het enthousiasme om verder te gaan zoeken waar het probleem zich bevond op Windows niveau vrij minimaal. Gelukkig stond een verhuis van deze applicatie naar een nieuwe server met de meest recente versie van Windows Server gepland. Enkele minuten later kon de toepassing getest worden op de nieuwe server en op deze versie van Windows Server verliep de TLS renegotiate zonder problemen! 

Sidebar TLS handshake

Een TLS-verbinding komt tot stand door het samenwerken van de client (browser) en de server. De client begint de TLS-verbinding met een CLIENT HELLO message. In die message geeft de client aan welke cypher suites, signature algoritmes en hash algoritmes deze ondersteunt. De server antwoord met reeks messages die begint met SERVER HELLO en eindigt met SERVER HELLO DONE.
Daartussen komt altijd een SERVER KEY EXCHANGE message, een CERTIFICATE message en optioneel een CERTIFICATE REQUEST message.

In de SERVER KEY EXCHANGE message geeft de server aan welke cypher suite, signature algoritme en hash algoritme gebruikt zal worden om de TLS-verbinding op te zetten. De CERTIFICATE message bevat het x509 certificaat dat de server identificeert. De CERTIFICATE REQUEST message geeft aan dat de client een x509 certificaat moet doorsturen om de client te identificeren.

Indien een CERTIFICATE REQUEST message verstuurd werd stuurt de client daarop een CERTIFICATE message.
Deze bevat het ceritificaat dat de client identificeert (het certificaat in deze message is het certificaat dat je kan selecteren bij het aanmelden met eID)

Daarna volgt een CLIENT KEY EXCHANGE message waarbij de client de sessie parameters voor de TLS verbinding doorgeeft aan de server.

Daarna, en enkel wanneer de client een certificaat doorstuurde, volgt een CERTIFICATE VERIFY message. Deze bevat de handshake informatie van de sessie versleuteld met de private key van het certificaat. Hiermee kan de server valideren dat de client wel degelijk de eigenaar is van het doorgestuurde certificaat (of toch op z'n minst de private key ervan bezit, wat op hetzelfde neerkomt).

Daarna stuurt de client een CHANGE CYPHER SPEC message door die aangeeft hoe alle volgende messages encrypt zullen worden en sluit af met een FINISHED message.
De server antwoordt met een analoge CHANGE CYPHER SPEC message en sluit ook af met een FINISHED message.
Hierna is de TLS verbinding tot stand gekomen.

Bij TLS renegotiation stuurt de server een HELLO REQUEST message naar de client. De client beantwoordt deze message met een CLIENT HELLO message die het volledige handshake proces terug opstart.