Przeczesanie zajęło 41 minut
30 lipca ktoś przeszedł przez 1196 adresów bitcoinowych i opróżnił je, zabierając 1082,65 bitcoina o wartości około 70,2 miliona dolarów, w oknie 41 minut. Nikt nie sforsował zamka. Nie dotknięto żadnego urządzenia, nie oszukano żadnego użytkownika, nie włamano się na żaden serwer. Napastnik niczego z tego nie potrzebował, ponieważ klucze prywatne chroniące te adresy dało się wyliczyć od zera. Pierwsze doniesienia szacowały stratę na blisko 38 milionów dolarów; gdy badacze skończyli liczyć, kwota sięgnęła niemal dwukrotności.
Urządzenia, o które chodziło, to sprzętowe portfele Coldcard produkowane przez Coinkite, czyli dokładnie ta kategoria produktu, którą kupuje się po to, by trzymać klucze z dala od sieci. To właśnie sprawia, że zdarzenie zasługuje na godzinę uwagi każdego właściciela, cokolwiek sądzi o bitcoinie. Awaria nie nastąpiła na granicy zewnętrznej, na którą wszyscy planują budżet. Nastąpiła w chwili, gdy sekret był tworzony, na lata przed tym, nim ktokolwiek spróbował go ukraść.
Makro ustawione na zero włączyło wariant zapasowy
Własna relacja techniczna Coinkite jest niezwykle szczera co do mechanizmu. W marcu 2021 roku, podczas migracji do biblioteki libsecp256k1 z Bitcoin Core, generowanie ziaren przekierowano z procedury wywołującej sprzętowy generator liczb losowych urządzenia do funkcji ogólnego przeznaczenia. Ta nowa ścieżka rozwiązywała się do programowego wariantu zapasowego MicroPythona zamiast do sprzętowej implementacji Coldcard. Sam kod zapasowy istniał od maja 2018 roku i aż do tamtej migracji nigdy nie dotykał generowania ziaren.
Powód, dla którego w ogóle się wkompilował, wart jest przepisania do własnej listy kontrolnej. Osłona wokół wariantu zapasowego sprawdzała, czy makro konfiguracyjne jest zdefiniowane, a nie czy ustawiono je na jeden. Programiści ustawili je na zero w znaczeniu, że generator sprzętowy nie jest tam potrzebny, a makro ustawione na zero nadal pozostaje makrem zdefiniowanym. Osłona odczytała obecność wartości zamiast samej wartości i włączyła wariant zapasowy. Nikt nie napisał słabej kryptografii. Generator sprzętowy istniał i działał. Przestał być jedynie tym, z czego czerpano ziarno.
Minęło pięć lat, a każdy test wciąż był zielony
Na urządzeniach Mk2 i Mk3 z oprogramowaniem od 4.0.1 do 4.1.9 powstałe ziarna niosły około 40 bitów entropii zamiast 128, które powinna mieć fraza dwunastowyrazowa. Na Mk4, Mk5 i Q obraz był lepszy, lecz nie bezpieczny: inżynierowie wmieszali wartości z elementów bezpieczeństwa w stan generatora jako, wedle sformułowania Coinkite, zapas dla zapasu, co podniosło tamte ziarna do mniej więcej 72 bitów. Obie liczby są katastrofalne w ten sam sposób. Losowości nie da się zobaczyć. Klucz mający za sobą 40 bitów podpisuje transakcje, weryfikuje adresy i odtwarza się z kopii dokładnie tak samo jak klucz ze 128, więc każdy test funkcjonalny, który firma i jej klienci uruchamiali przez pięć lat, wypadał pomyślnie, i słusznie, podczas gdy produkt był zepsuty.
Coinkite podaje ponadto szczegół, który większość dostawców by zakopała. Kilka tygodni temu, pisze firma, użyto jednego z najlepszych dostępnych modeli sztucznej inteligencji do przeglądu własnego kodu pod kątem problemów bezpieczeństwa i nie znalazł on tego błędu. Warto się przy tym zatrzymać, zanim kolejny dostawca oznajmi, że jego kod przejrzał model. Wada nie była z perspektywy czasu subtelna ani ukryta, ale mieszkała w spoinie między konfiguracją kompilacji a założeniem kryptograficznym, czyli dokładnie w tym szwie, który recenzent czytający pod kątem jakości kodu najrzadziej potraktuje jako granicę bezpieczeństwa.
Poprawka chroni następny klucz, nie poprzedni
Coinkite wydało 31 lipca poprawione oprogramowanie układowe dla każdego dotkniętego modelu i gałęzi: 4.2.0 dla Mk2 i Mk3, 5.6.0 dla Mk4 i Mk5, 1.5.0Q dla Q oraz odpowiadające im wydania edge. Następnie opublikowało zdanie ważące więcej niż sama łatka. Aktualizacja oprogramowania układowego nie zmienia ani nie naprawia istniejącego ziarna. Zalecenie firmy brzmi: zainstalować poprawione oprogramowanie, wygenerować nowe ziarno na zaktualizowanym urządzeniu, zapisać i zweryfikować jego kopię zapasową przed jakąkolwiek wpłatą, potwierdzić nowy adres odbiorczy na ekranie urządzenia, wysłać małą transakcję próbną i dopiero wtedy przenieść pozostałe środki.
To migracja, a nie aktualizacja, i w tym rozróżnieniu mieści się cała lekcja. Dwie rzeczy mogły uratować portfel utworzony w dotkniętym oknie: pięćdziesiąt niezależnych, prywatnych rzutów kostką wprowadzonych przez własną funkcję kostki urządzenia, ponieważ Coldcard wliczał je do ziarna, albo mocne, niepowtarzalne hasło dodatkowe, które stoi jako osobna bariera przed słabym ziarnem. Coinkite i tak radzi nawet użytkownikom z takim hasłem migrować, gdy tylko będzie to wykonalne. TAPSIGNER, OPENDIME i SATSCARD opierają się na innych bazach kodu i nie są dotknięte.
Inwentaryzuj to, co wygenerowałeś, nie tylko to, co uruchamiasz
Niemal każdy proces łatania, jaki właściciel kiedykolwiek zatwierdził, traktuje wersję oprogramowania jako jednostkę ryzyka. Dowiadujesz się, że wersja jest podatna, aktualizujesz ją i narażenie się kończy. Wady entropii łamią ten model całkowicie, bo szkoda nie tkwi w działającym kodzie, lecz w przedmiotach, które kod wydał i przekazał: kluczach, tokenach, identyfikatorach sesji, kodach odzyskiwania, sekretach API, certyfikatach. Te przedmioty przeżywają wersję, która je stworzyła, wędrują do kopii zapasowych i systemów obcych i niosą słabość ze sobą na stałe. Aktualizacja generatora kończy produkcję złych sekretów. Ze stanem posiadania nie robi nic.
Pytanie do każdego dostawcy, którego produkt tworzy sekrety w twoim imieniu, nie brzmi więc wyłącznie, które wersje są dotknięte. Brzmi ono: które sekrety wygenerowano na dotkniętej wersji, jak się je wylicza i jaka jest ścieżka wymiany. Dotyczy to o wiele więcej niż portfeli sprzętowych: modułu HSM w stosie płatniczym, urzędu certyfikacji, linii wdrażania urządzeń, dostawcy tożsamości wydającego długowieczne tokeny. Wszędzie tam, gdzie maszyna bije coś, na czym później polegasz, wadliwe okno jest tym, co należy zinwentaryzować, a prawie nikt tego nie ewidencjonuje.
Czytaj dalej: Trzy firmy decydują, czy twój telefon zostanie tani | Siemens i Schneider trafiły tam 22 lipca



