[Home/Nieuws]  [Magazines]  [Meetings]  [Downloads]  [Redaktie]  [Geschiedenis
 

Veiligheidsonderzoek ABN AMRO HomeNet 2.0
Door Bastiaan Bakker en Richard Odekerken

Hoofdstuk 3 - De Vasco Access Key II

3. De Vasco Access Key II

3.1 Functionaliteit

De officiële voor de calculator (vroeger door ABN AMRO ook wel 'numculator' genoemd) is een 'authentication token'. Het basisidee is dat de gebruiker zich kan autoriseren door het bezit van dit token, of beter gezegd: door de geheime sleutel die in het token vastgelegd is. De gebruiker kan aantonen dat zijn token een bepaalde sleutel heeft door middel van een zogeheten challenge/response-mechanisme. Basis hiervan is het idee dat de geheime sleutel nooit bekend wordt gemaakt, maar dat door het stellen van een vraag (de challenge) toch duidelijk wordt dat de geheime sleutel de juiste is - doordat het antwoord (de response) alleen van iets of iemand in het bezit van de betreffende sleutel afkomstig kan zijn.

 Tijdens de communicatie met de bank wordt een challenge aan de gebruiker gepresenteerd. De gebruiker dient deze op de calculator in te voeren. Het resultaat dient van het display van de calculator overgenomen te worden in het HomeNet pakket.
Voorafgaand aan de publicatie van dit hoofdstuk hebben wij dit ter commentaar voorgelegd aan de ABN AMRO. Zij hebben ons vervolgens in contact gebracht met Vasco. De feedback van Vasco is verwerkt in de gekleurde balken die zo nu en dan tussendoor staan.
Wij danken ABN AMRO en Vasco hartelijk voor de feedback en medewerking die wij mochten ontvangen! 

3.1.1 Uiterlijk

De calculator bevat elf toetsen (de cijfers 1 tot en met 9, en nog twee blanco - ongebruikte - toetsen). Een ingedrukt cijfer verschijnt kort op het display. Wanneer een challenge is ingevoerd, verschijnt na enkele seconden de response op het display.
De calculator beschikt aan de bovenzijde over een optische interface: vier naast elkaar geplaatste lichtgevoelige diodes.

 Op de achterzijde van de calculator is een serienummer afgedrukt. Op de achterkant van de calculator staan tevens een tweetal patentnummers (4,599,489 en 4,609,777), en het Internet-adres http://www.vdsi.com vermeld. Dit is de fabrikant: Vasco Data Security Incorporated (tegenwoordig 'Vasco'). Na enig zoeken blijkt dat de door ABN AMRO gebruikte calculator een Vasco Access Key II is. Volgens informatie op de website van Vasco bevat iedere calculator een unieke geheime sleutel waarmee volgens een proprietary algoritme uit de challenge (C) de response (R) berekend wordt: R = Fkuser(C). Verder wordt vermeld dat de sleutel periodiek gewijzigd wordt, opdat de mapping van C naar R niet steeds hetzelfde blijft. 

Intussen hebben we hyperlinkjes aangebracht naar de betreffende patenten. We hebben ons in eerste instantie niet gerealiseerd dat deze natuurlijk gewoon op te vragen zijn. Deze patenten beschrijven overigens een ander algoritme dan dat in de Access Key II. 

3.2 Initiele observaties

Aan de hand van uit HomeNet sessies verzamelde challenge/response paren en het uitproberen van codes op de calculator kon het volgende geconstateerd worden: 
  • Het cijfer '9' is de 'aan'-knop van de calculator: het is altijd het eerste cijfer in een challenge en komt verder niet voor. We zullen de 9 dan ook niet verder beschouwen als onderdeel van de eigenlijke challenge C. 
  • Challenges zijn bijna altijd 6 cijfers lang (exclusief de '9') maar soms 7 of 8 cijfers. 
  • Door de bankserver opgegeven challenges beginnen altijd met 5, 6, 7 of 8, nooit 1, 2, 3 of 4. 
  • Voor iedere cijfercombinatie abcd, waar a Î {5,6,7,8} is er precies één challenge abcdef(gh) die met deze combinatie begint. De combinatie ef(gh) is verschillend voor verschillende waarden van abcd, maar voor een vaste abcd gelijk voor verschillende calculators. Dus bijvoorbeeld challenge 511142 is geldig voor alle calculators. Het lijkt er dus op dat de eerste vier cijfers het random gedeelte van de challenge zijn, en de overige cijfers een soort checksum. 
  • Responses zijn 6 karakters lang. Ieder karakter is één van de volgende tekens: 02345789ACEFHLPU. De HomeNet handleiding meldt dat voor '0' ook 'O' gebruikt mag worden, en ook 'S' voor '5' en 'B' voor '8'. Ieder karakter bevat dus (maximaal) 4 bits informatie. 
  • Na iets meer dan 3 dagen (aangenomen wordt na 218 seconden » 3.03 dagen) wijzigt de mapping van challenge naar response. 
  • De responses bevatten een gelijke verdeling van tekens (ieder teken komt even vaak voor) behalve op positie 5, waar maar 8 van de 16 tekens voorkomen (maar deze 8 dan ook weer gelijk verdeeld). Na een wijziging van de challenge/response mapping wijzigt ook deze subset van tekens. Na een volgende wijziging van de mapping komt de eerste subset weer voor. We concluderen hier (voorlopig) uit dat 1 bit van het 5e karakter in de respons gelijk is aan (of de negatie van) bit 18 van de interne tijdklok (aangenomen dat deze klok in seconden telt). 
  • Inderdaad gaat het hier om een synchronisatie-bit, waarmee de server die de response moet controleren, erachter kan komen of het token zich in hetzelfde tijdframe van drie dagen (zoals dat in de vorige bullet genoemd is) bevindt. Hiermee worden problemen voorkomen die zouden kunnen optreden wanneer de klok van het token niet geheel synchroon loopt met die klok op de server, met als gevolg dat token en server zich soms niet in hetzelfde tijdframe zouden bevinden. 
  • De calculator reageert ook op sommige codes die beginnen met een 2, bijvoorbeeld 211138. De bijbehorende antwoorden wijzigen echter veel sneller dan eens in de drie dagen, namelijk na ruim een uur (aangenomen wordt na 212 seconden » 1.14 uur). 
De challenge bestaat dus uit 2+3*3=11 bits, de response uit 6*4=24 bits, waarvan één afleidbaar uit de tijd. Aannames: 
  • De cijfers 1 t/m 8 in de challenges representeren de waarden 0 t/m 7 in die volgorde. 
  • De karakters in de response representeren de waarden 0 t/m 15 in een nog te bepalen volgorde. 
  • De calculator bevat een interne klok die seconden telt. 

3.3 PRFZJHP6.tar.gz

Wanneer we op Internet zoeken naar meer informatie over deze Vasco Access Key II, komen we al snel een pagina tegen met daarop de winnaars van een Java wedstrijd: The Java Cup International Contest Winners Circle, op de URL http://sunsite.utk.edu/winners_circle/index.html.

 Hierop staat een inzending van Vasco, met de volgende begeleidende tekst:

 "This applet is based on VDSI's patented access control technology called the Access Key II(TM). The Access Key II(TM) is a one-time password generator used for extended user authentication. The Key operates as a challenge/response token, where the challenge can be read by the token optically or through keypad entry. Java provides us with the ability to present the optical challenge in a Web document, which can then be used for entry into a secure Web site." 

Het mooie is dat de tekst wordt begeleid door een 'Download' link. Dit levert ons een bestand met de obscure naam PRFZJHP6.tar.gz op. Uitpakken van dit bestand levert allerlei moois op:

  • BitString.class 
  • Flash.class en Flash.java 
  • TopPiece.class 
Bovendien een aantal HTML bestanden, een directory met GIF plaatjes, en nog wat zaken:
  • test_log 
  • servauth.cgi 
  • keyfile2.txt 
Wanneer we het Java applet starten, blijken zo we de optische interface van de Access Key II te kunnen gebruiken. Het wordt al snel duidelijk dat bij dit applet nog wat logica op een webserver hoort, die de gegenereerde challenge kan controleren, en vervolgens 'Goed' of 'Fout' zegt.

 Dit gaat als volgt in zijn werk:
 
 

  1. Het applet genereert een (in dit geval random) key. 
  2. De gebruiker houdt de Access Key tegen het computerscherm, en voert de gegenereerde response in in het applet. 
  3. Tevens voert de gebruiker zijn gebruikersnaam in in het applet. 
  4. De gegevens (challenge, response, en gebruikersnaam) worden via het HTTP-protocol naar een programma - een zogenaamde CGI-binary- op de webserver toegezonden. 
  5. De CGI-binary zoekt aan de hand van de gebruikersnaam het serienummer van de gebruikte Access Key op. Hier blijkt het bestand keyfile2.txt voor te dienen. 
  6. Aan de hand van het serienummer wordt de response gecontroleerd. 
Op de betreffende website staat nog steeds een pagina online waar je met de optische interface kan spelen! 

3.4 Verder onderzoek

De hierboven beschreven software bood ons zeer veel nuttige informatie over de werking van de calculator. In de komende paragrafen beschrijven we een aantal van onze bevindingen. 

3.4.1 Bepaling van de representatie van de respons

De respons van de calculator bestaat uit 6 karakters die ieder 16 waarden kunnen aannemen. We mogen aannemen dat ieder digit 4 bits, oftewel 1 hexadecimaal digit van de respons representeert. Een van de eerste dingen die we wilden bepalen was de mapping van hexadecimale naar display representatie van de respons. Toen we eenmaal de CGI software hadden gevonden en gedecompileerd was dit triviaal, maar in eerste instantie richtten we ons hiervoor op de codes die beginnen met 2.

 Bij de met 2 beginnende codes berekent de calculator niet de gebruikelijke respons, maar geeft een permutatie terug van de inputbits en de bitrepresentatie van de tijd. Zie onderstaande tabel voor de resultaten van vier verschillende codes op twee tijdstippen. Door nu naar de verschillende resultaten te kijken als je één bit in code wijzigt, kun je afleiden welke karakters een waarde hebben die maar één bit verschilt. (Uit de onderstaande tabel zijn bijvoorbeeld 4 - 5 en U - 2 af te leiden.) Ook de responses op verschillende tijdstippen helpen hierbij. Vervolgens keken we naar de resultaten bij twee verschillende bits, en zo verder.
 
 
Code Resultaat 1 Tijdstip 1 Resultaat 2 Tijdstip 2
221133 42UU27 01:01 42UUC7 01:36
223153 52UU27 01:02 52UUC7 01:35
225172 42U227 01:02 42U2C7 01:35
227112 52U227 01:03 52U2C7 01:34

Tabel 1: Codes en resultaten in de 2-range

 Hieruit valt een hyperkubus te bouwen met op ieder hoekpunt een karakter, zie onderstaande figuur.

 Figuur 2: Hyperkubus bitrepresentaties

 Helaas is de oriëntatie van de kubus (dus welk hoekpunt welk bit en welke bitwaarde representeert) met bovenstaande methode niet te bepalen. Toen beschikten we echter al over de servauth CGI. Hierin zijn vlak na elkaar de volgende strings te vinden:
 
 

9A7F8LCEP304UH25

0123456789ABCDEF

Aangezien de hier gesuggereerde volgorde volledig overeenkwam met de gevonden hyperkubus, hebben we van hieraf aangenomen dat dit de correcte mapping is. Na het volledig decompileren van servauth.cgi werd deze aanname bevestigd.
 
 

3.4.2 Bepaling van de opbouw van de challenge

Wanneer men een correcte challenge in de calculator invoert reageert het met een respons, op andere invoer reageert het niet. Op deze manier is het dus mogelijk te bepalen welke challenges geldig zijn. Voordat we in het bezit van bovenstaande software kwamen hebben zo de lijst opgesteld met alle geldige challenges. 

Met behulp van de Java applet was echter veel sneller af te leiden hoe de opbouw van de challenge in elkaar zit (zie Appendix C). 

De eerste vier digits zijn de eigenlijke challenge, gevolgd door een 6 bit Cyclische Redundantie Checksum (CRC) gebaseerd op generator polynoom 1000011. Vervolgens wordt het resultaat gebitstuffed om de sequence 110100 te vermijden. Bij invoer van de challenge in de calculator via de lichtsensoren geldt deze sequence namelijk als markering van de start van de challenge. Dankzij de bitstuffing zijn sommige challenges 7 i.p.v 6 digits lang. 
Opgemerkt dient te worden dat challenges altijd met 5, 6, 7, of 8 beginnen (kort gezegd: het eerste bit is altijd gelijk aan 1). De codes die met 1, 2, 3 en 4 beginnen zijn geen geldige challenges. 

3.4.3 Decompileren van servauth.cgi

Het CGI programma dat de reponses van de Access Key moet controleren is een executable voor het Sun SPARC32 platform. Het is een C programma, gecompileerd met de GNU C Compiler (gcc) versie 2.6.0 zonder optimalisatie maar met debugging optie. Deze compileeropties maakten het voor ons veel makkelijker om de executable te decompileren tot C source. Daarnaast is SPARC32 assembler vrij makkelijk te lezen. In tegenstelling tot de Intel x86 instructieset is de SPARC instructieset namelijk vrij orthogonaal, waardoor de compiler geen moeilijke (= moeilijk decompileerbare) sprongen hoeft te maken voor registerallocatie. 

Het resultaat van het reverse engineeren van servauth.cgi is te vinden in Appendix D

3.4.4 Het challenge/response algoritme van de Access Key II

Het servauth.cgi decompilaat bevat een implementatie van het algoritme dat de Access Key II gebruikt om de respons op een challenge te berekenen. Deze code blijkt echter niet door servauth gebruikt te worden voor de verificatie van de respons. In plaats daarvan voert het de inverse functie uit op de respons. Het challenge/response algoritme is dus een encryptie functie en niet zoals verwacht een hashfunctie. 

3.4.5 De keyfile

Het bestand 'keyfile2.txt' bevat het volgende: 
java1,2-0022305-4,7327,E342294EFFA7DDEF,D4D58AA4,0B5D25

java2,2-0022306-4,7327,151629584C856BEF,D4D59329,4BEC5B

java3,2-0022307-4,7327,03CC2962C0A918EF,D4D52BB2,4B6C97

java4,2-0022310-4,7327,D0FF29807C31EFEF,D4D59C5D,4B9835

java5,2-0022311-4,7327,E8DD298A86FF80EF,D4D5379A,4B6097

java6,2-0022313-4,7327,F86C299E8F7BA5EF,D4D591A3,4BE667

testuser,2-0051814-4,7127,CA9A6505B9F583CD,D4D547BD,1DD34F

akldemo,2-0051814-4,7127,CA9A6505B9F583CD,D4D547BD,1DD34F

In dit bestand staan per regel de sleutels voor een calculator. De velden zijn: 
  • UserName 
  • SerialNumber 
  • DayCut 
  • Today 
  • Tomorrow 
  • Root 
'DayCut' geeft de dag weer waarop de calculator is geinitialiseerd, geteld in dagen sinds 1 maart 1976. 'Today' is de werksleutel K0 zoals tijdens de initialisatie van de calculator ingesteld. Deze sleutel wordt door de calculator na iedere 218 seconden gewijzigd.

 'Tomorrow' is de Key Transforming Key KKTK aan de hand waarvan de werksleutel iedere 218 seconden gewijzigd wordt:
Kn+1 = g(KKTK, Kn).

 'Root' is een statische sleutel KB voor blanking van de challenges, vergelijkbaar met de blanking methode gebruikt in het DESX algoritme: bij de challenge C wordt eerst, modulo 2, de blanking key opgeteld voordat het tot de respons R versleuteld wordt met de werksleutel:
R = E(Kn , C Å KB ).
 
 

3.4.6 test_log

Dit bestand bevat een aantal door servauth.cgi gelogde challenges en responses. Een paar regels: 
Thu Mar 28 14:38:13 1996   user=tesuser resp=L5UU94 num=1532

Thu Mar 28 15:13:34 1996   user=testuser resp=l9ulp3 num=1545

'Num' is een random getal waaruit de CGI de challenge afleidt. Aangezien in de log ook de respons, de user en tijdstip van berekening staan, kunnen we deze waarden gebruiken als testvectoren om te controleren of onze gereverse engineerde implementatie correct is.
 
 
  1. Bepaling van de werksleutel Kn uit K0 en KKTK. In de functie GetChanges() wordt de waarde van n bepaald. Vervolgens wordt in ApplyChanges() de key transform functie g() n maal uitgevoerd. Helaas worden in GetChanges() te kleine variabelen gebruikt, waardoor vanaf 1998 de waarde van n verkeerd berekend wordt. Daarnaast is de gebruikte methode om n te berekenen onbegrijpelijk: de huidige tijd zoals gegeven door time() wordt eerst opgesplitst in jaar, maand, dag, etc. en aan de hand van deze waarden wordt n geschat. Schrikkeljaren worden 'gecorrigeerd' door voor een jaar 365.25 dagen te tellen. Evenzo wordt voor alle maanden 30.6 dagen berekend. Deze methode zit er desontdanks in veel gevallen meer dan een dag naast, wat een verkeerde waarde van n op kan leveren. Dat terwijl het hele algoritme vervangen had kunnen worden door: n = (time() - 194486400) / 218 - DayCut. (194486400 is 1 maart 1976 weergegeven in seconden sinds 1 januari 1970 UTC.) 
  2. Het gaat hier om een oude versie van het algoritme, wat ondermeer in Pascal en Fortran is geïmplementeerd en pas later is geport naar C. Later is nog een correctiefactor toegevoegd om de genoemde onnauwkeurigheid te ondervangen. De code die wij hebben bekeken is alleen gebruikt voor de servauth.cgi en is niet gelijk aan de code op de bankserver, waarmee de challenge wordt gecontroleerd. De bankserver bevat deze bug dus niet! 
  3. Bij de challenge wordt modulo 1 de blanking key KB opgeteld. 
  4. De volgende stap is het hart van de challenge-response berekening. De functie DeriveAnswer() encrypt de challenge C met sleutel Kn
  5. Als laatste stap wordt in de functie UnMapAnswer() het resultaat R van DeriveAnswer() vertaald naar de digits op het display van de calculator. In deze routine wordt ook een finale permutatie uitgevoerd van de bits van R. Onduidelijk is waarom deze permutatie wordt uitgevoerd: het biedt geen enkele verbetering van de cryptografische sterkte van het challenge-response algoritme. Dergelijke mutaties worden overigens ook in andere cryptografische algoritmes - zoals DES - uitgevoerd, en ook daar is de daadwerkelijke functie niet bekend. 

3.4.7 Security van DeriveAnswer()

De encryptiefunctie in DeriveAnswer() is geen block cipher, maar gebaseerd op stroomversleuteling, alleen wordt als output niet de hele bitstream die gegenereerd wordt gebruikt, maar alleen de state na een vast aantal rondes. 

Het algoritme kan gezien worden als een Non-linear Feedback Shift Register (NFSR). De state van het register bestaat uit 23 bits die initieel met de challenge gevuld worden plus nog een extra bit. De wijze waarop dit laatste bit wordt gebruikt zorgt ervoor dat het algoritme geen puur FSR is.

 Naast het Feedback register worden nog 3 andere vectoren gebruikt: uit de sleutel genereert DeriveAnswer() 'poly', 'nla' en 'nlb'. Deze drie vectoren zorgen ervoor dat de feedback iedere keer steeds anders is. De nieuwe waarde van de calculatie bestaat uit twee lussen: in de binnenste lus, die 23 maal wordt uitgevoerd, wordt het register één keer rondgeschoven. De buitenste lus herhaalt dit 225 keer. 

Aangezien onze eigen cryptografische expertise beperkt is, hebben we op het CCC Camp/Congres 1999 aan expert Ian Goldberg zijn mening over het algoritme gevraagd. Hij kon ter plekke geen zwakke plek vinden in het algoritme. Dit komt onder andere door het erg grote aantal ronden. Om Bruce Schneier aan te halen: 'with enough rounds almost any crypto algorithm can be secure'. Dit maakt het algoritme dus wel erg langzaam. Aan de andere kant: de traagheid geldt meer voor de software implementatie dan voor de calculator zelf. 
Een groot voordeel van een langzaam algoritme is dat het brute force aanvallen bemoeilijkt. Het gaat hier puur om een challenge/response algoritme, dat slechts zeer kleine hoeveelheden data hoeft te versleutelen. Daarbij is snelheid niet echt van belang. 
Feedback Shift Registers kunnen in hardware vaak zeer efficient gebouwd worden. Figuur 3 beeldt de binnenste lus van het algoritme af, opgebouwd in schakellogica. 

Figuur 3: De binnenste lus van DeriveAnswer() geimplementeerd in schakellogica

 Het feit dat er geen zwakke plek gevonden is wil overigens niet zeggen dat het algoritme veilig is.

 Het betreft een proprietary, nog niet gepubliceerd algoritme, en wij zijn niet op de hoogte van een publiek bekend onderzoek naar de sterkte ervan. Los daarvan is er uberhaupt nog zeer weinig theorie over schuifregisters met niet-lineaire terugkoppeling gepubliceerd. Het is ons onduidelijk waarom er niet voor een publiek goed getest algoritme gekozen is. 
Dergelijke algoritmen in de NFSR-familie zijn veel gebruikt (en getest) in de militaire sector. Er zijn dus wel degelijk onderzoeken naar de sterkte van dit algoritme, maar die zijn niet wijd gepubliceerd. 

3.4.8 Security van ApplyChanges()

De ApplyChanges() functie is een nonlineaire mapping van de 64-bit werksleutel met een 32-bit transformsleutel naar een nieuwe 64-bit werksleutel. In de servauth CGI wordt in ApplyChanges() de oorspronkelijke werksleutel omgerekend naar de huidige werksleutel door de transform N keer te herhalen. In de calculator wordt de transform iedere drie dagen maar één keer uitgevoerd. 

De transform zelf bestaat uit een dubbele lus. De buitenste lus loopt een voor een alle bits in de werksleutel af. Indien de waarde van een bit 1 is wordt de binnenste lus uitgevoerd. Hierin worden afhankelijk van de transform key de helft van de bits in de werksleutel geflipt. 

Interessant genoeg beschouwt ApplyChanges() de eerste zestien bits van de tranform key als een andere vector dan de andere zestien bits. Ze worden namelijk in twee lussen gekopieerd naar de transform vector waarmee de eigenlijke berekening wordt gedaan. In de bijgelerde keyfile zijn de eerste 16 bits van alle transform keys gelijk (waarde D4D5). Het lijkt er dus op dat de het random gedeelte, dus de eigenlijke transforming key, maar 16 bits groot is. 

Zelfs als bovenstaande aanname niet waar is, is de lengte van de Key Transforming Key zo klein, dat deze met een known plain text attack via brute force te achterhalen zou kunnen zijn. Dat wil zeggen dat als men de werksleutel van de calculator kan achterhalen het geen probleem zal zijn de KTK te achterhalen en dus ook alle volgende werksleutels. We mogen aannemen dat dit dan ook niet het doel van deze functie is. Het is naar alle waarschijnlijkheid slechts bedoeld om aanvallen op de werksleutel te bemoelijken: triviale werksleutel transformaties zoals additie van een vast getal kunnen differentiële cryptanalyse behoorlijk lastig maken, en dat is hier ook zeker het geval. 
Bovenstaande aanname is juist: Wanneer de werksleutel achterhaald zou kunnen worden, is het algoritme gekraakt en doet de KTK er weinig meer toe. De toepassing van een KTK is puur bedoeld om differentiële cryptanalyse te bemoeilijken, waardoor de werksleutel moeilijker te achterhalen is. 

Vorige  Inhoudsopgave  Volgende
De informatie in 't Klaphek dient slechts een educatief doel. Gebruik van deze informatie zou strafbaar kunnen zijn. De redaktie wijst iedere verantwoordelijkheid voor gebruik door lezers van de in 't Klaphek opgenomen informatie af. De mening van een auteur weerspiegelt niet noodzakelijkerwijs de mening van de redaktie of uitgever.