Tyveriet tog 41 minutter
Den 30. juli gennemgik nogen 1.196 bitcoinadresser og tømte dem for 1.082,65 bitcoin til en værdi af omkring 70,2 millioner dollar i et vindue på 41 minutter. Ingen dirkede en lås op. Ingen enhed blev rørt, ingen bruger narret, ingen server brudt. Angriberen havde ikke brug for noget af det, for de private nøgler, der beskyttede de adresser, kunne regnes ud fra bunden. De første meldinger satte tabet nær 38 millioner dollar; da forskerne var færdige med at tælle, landede tallet på næsten det dobbelte.
De berørte enheder var Coldcard-hardwarepunge fremstillet af Coinkite, altså netop den produktkategori, man køber for at holde nøgler væk fra netværk. Det er dét, der gør hændelsen en times opmærksomhed værd for enhver ejer, uanset hvad vedkommende mener om bitcoin. Svigtet skete ikke ved den ydre grænse, som alle budgetterer med. Det skete i det øjeblik, hemmeligheden blev skabt, år før nogen forsøgte at stjæle den.
En makro sat til nul tændte reserven
Coinkites egen tekniske redegørelse er usædvanlig åbenhjertig om mekanismen. I marts 2021 blev seed-genereringen under en migrering til Bitcoin Cores libsecp256k1 ledt fra den rutine, der kaldte enhedens hardwaregenerator af tilfældige tal, over til en almen funktion. Den nye sti endte i MicroPythons softwarereserve i stedet for Coldcards hardwareimplementering. Reservekoden havde eksisteret siden maj 2018 og havde aldrig rørt seed-genereringen før netop den migrering.
Grunden til, at den overhovedet blev kompileret med, hører hjemme på jeres egen tjekliste. Vagten omkring reserven afprøvede, om en konfigurationsmakro var defineret, ikke om den var sat til ét. Udviklerne havde sat den til nul i betydningen, at hardwaregeneratoren ikke var nødvendig dér, og en makro sat til nul er stadig en defineret makro. Vagten læste værdiens tilstedeværelse i stedet for selve værdien og tændte reserven. Ingen skrev svag kryptografi. Hardwaregeneratoren fandtes og virkede. Den var blot ikke længere dét, seedet blev trukket fra.
Fem år gik, og hver eneste test forblev grøn
På Mk2- og Mk3-enheder med firmware 4.0.1 til 4.1.9 bar de fremkomne seeds omkring 40 bits entropi i stedet for de 128, en tolvordsfrase bør have. På Mk4, Mk5 og Q var billedet bedre, men ikke sikkert: ingeniører havde blandet værdier fra sikkerhedselementerne ind i generatorens tilstand som, med Coinkites udtryk, en reserve for reserven, hvilket løftede de seeds til cirka 72 bit. Begge tal er katastrofale på samme måde. Tilfældighed kan man ikke se. En nøgle med 40 bit bag sig signerer transaktioner, verificerer adresser og genskabes fra sikkerhedskopi nøjagtigt som en med 128, så alle funktionstests, som virksomheden og dens kunder kørte i fem år, blev bestået med rette, mens produktet var i stykker.
Coinkite oplyser desuden en detalje, som de fleste leverandører ville have begravet. For nogle uger siden, skriver selskabet, brugte det en af de bedste tilgængelige AI-modeller til at gennemgå sin egen kode for sikkerhedsproblemer, og den fandt ikke denne fejl. Det er værd at dvæle ved, før den næste leverandør fortæller, at deres kode er gennemgået af en model. Fejlen var i bagklogskabens lys ikke subtil og ikke skjult, men den boede i samlingen mellem en byggekonfiguration og en kryptografisk antagelse, altså netop den søm, som en gennemlæser med fokus på kodekvalitet mindst sandsynligt behandler som en sikkerhedsgrænse.
Rettelsen beskytter den næste nøgle, ikke den forrige
Coinkite udsendte den 31. juli rettet firmware til hver berørt model og gren: 4.2.0 til Mk2 og Mk3, 5.6.0 til Mk4 og Mk5, 1.5.0Q til Q samt de tilsvarende edge-udgaver. Derpå offentliggjorde selskabet den sætning, der vejer tungere end rettelsen. En firmwareopdatering ændrer eller reparerer ikke et eksisterende seed. Anvisningen er at installere den rettede firmware, danne et nyt seed på den opdaterede enhed, nedskrive og efterprøve dets sikkerhedskopi før nogen indbetaling, bekræfte en ny modtageradresse på enhedens skærm, sende en lille prøveoverførsel og først derefter flytte de resterende midler.
Det er en migrering og ikke en opdatering, og i den skelnen ligger hele lektien. To ting kunne redde en pung skabt i det berørte vindue: halvtreds uafhængige, private terningkast indtastet via enhedens egen terningfunktion, da Coldcard regnede dem ind i seedet, eller en stærk, unik adgangsfrase, der står som en selvstændig barriere foran det svage seed. Coinkite råder alligevel også frasebeskyttede brugere til at migrere, så snart det er praktisk muligt. TAPSIGNER, OPENDIME og SATSCARD kører på andre kodebaser og er ikke berørt.
Optæl det, I frembragte, ikke blot det, I kører
Næsten enhver lappeproces, en ejer har godkendt, behandler softwareversionen som risikoenhed. Man erfarer, at en version er sårbar, opdaterer den, og eksponeringen ophører. Entropifejl bryder den model fuldstændigt, for skaden ligger ikke i den kørende kode, men i genstande, koden udsendte og rakte videre: nøgler, tokens, sessionsidentifikatorer, gendannelseskoder, API-hemmeligheder, certifikater. De genstande overlever den version, der skabte dem, vandrer ind i sikkerhedskopier og tredjepartssystemer og bærer svagheden med sig for altid. En opdateret generator standser produktionen af dårlige hemmeligheder. Ved beholdningen ændrer den intet.
Spørgsmålet til enhver leverandør, hvis produkt skaber hemmeligheder på jeres vegne, er derfor ikke kun, hvilke versioner der er berørt. Det er, hvilke hemmeligheder der blev frembragt på en berørt version, hvordan man opregner dem, og hvad udskiftningsvejen er. Det gælder langt ud over hardwarepunge: HSM'en i betalingsstakken, certifikatmyndigheden, linjen til enhedsudrulning, identitetsudbyderen der udsteder langtidsholdbare tokens. Overalt hvor en maskine præger noget, I siden læner jer op ad, er det fejlbehæftede vindue dét, der skal optælles, og næsten ingen fører bog over det.
Læs videre: Tre firmaer afgør, om din telefon forbliver billig | Siemens og Schneider kom med den 22. juli



