Coldcard Donanım Cüzdan Zafiyeti, 88 milyon doların üzerinde bitcoin çalınmasına neden oldu

iconMetaEra
Paylaş
AI summary iconÖzet
Yanlış yapılandırılmış bir RNG ile ilişkili bir Coldcard donanım cüzdan kusuru, 88 milyon doların üzerinde değerinde olan 594 BTC'nin çalınmasına neden oldu. Sorun, Coldcard Mk2, Mk3, Mk4, Q ve Mk5 modellerini etkiledi ve özel anahtarları kaba kuvvet saldırılarına maruz bıraktı. Beosin, toplu fonları birkaç Bitcoin adresine kadar izledi. Bu olay, CFT altında endişeleri artırıyor ve AB'nin kripto düzenlemelerini sıkılaştırması nedeniyle MiCA'ya uyumun aciliyetini vurguluyor.

88 milyon doların üzerinde kayıp: Coldcard donanım cüzdanı açıklığı analizi ve çalınan fonların izlenmesi 31 Temmuz'da, yaklaşık 500 Coldcard donanım cüzdanından toplam 594 Bitcoin çalındı ve bu miktar yaklaşık 38 milyon dolar değerindeydi. Daha sonra Coldcard cüzdanlarını üreten Coinkite şirketi, bu ürünün anahtar üretimi aşamasında bir güvenlik açıklığı olduğunu ve Coldcard Mk2, Mk3, Mk4, Q ve Mk5 gibi birçok nesil ürünü etkilediğini doğruladı.

Şu ana kadar bu güvenlik açıklarına yönelik saldırı nedeniyle kaybedilen tutar 88 milyon ABD dolarını aşmıştır ve saldırı hâlâ devam etmektedir. Coldcard cüzdan kullanıcıları, fonlarını hemen başka bir adrese aktarmalıdır. Beosin’in bu açıklara ilişkin analizi ve ele geçirilen fonların takibi aşağıdaki gibidir.

Birinci: Güvenlik Açığı Analizi

Coldcard firmware kodunun commit geçmişini analiz ederek, daha önceki Commit 37e4af5451c260c1e7d429fe8972c4cb5e68ee59'da MK4 yapılandırmasıyla ilgili birçok kod güncellemesi yapıldığını görebilirsiniz; mpconfigboard.h dosyasında şunlar yer alır:

// Kendi sürümümüz var bu kodun. #define MICROPY_HW_ENABLE_RNG (0)

MicroPython STM32 tarafında, bu makro, varsayılan donanım rastgele sayı üreticisi (RNG) bağlamasını ve genel rastgele sayı uygulamasını derleme yolunu kontrol eder. Bunun 0 olarak ayarlanması, varsayılan donanım RNG yolunun genel rng_get() fonksiyonunun arka planı olarak kullanılmasını engeller.

Açıklamada, geliştiricinin RNG'yi kendi kendine uygulayacağı belirtilmiştir; özelleştirilmiş rng.h dosyasını kontrol edildiğinde yalnızca iki MicroPython nesnesi tanımlandığı görülmüştür:

MP_DECLARE_CONST_FUN_OBJ_0(pyb_rng_get_obj);MP_DECLARE_CONST_FUN_OBJ_1(pyb_rng_get_bytes_obj);

Karşılık gelen uygulama:

/// \function pyb_rng_get()///// 30-bit donanım tarafından üretilen bir rastgele sayı döndürür: veya hata ver!//STATIC mp_obj_t pyb_rng_get(void){    // Yeni rastgele sayıyı al ve döndür    return mp_obj_new_int(rng_get_or_fault() >> 2);}
/// \function rng_get_bytes()/// Bir tamponu rastgele bitlerle doldurur; çağırıcı boyutlu bir tampon sağlamalıdır.STATIC mp_obj_t pyb_rng_get_bytes(mp_obj_t buffer_io) {
    mp_buffer_info_t bufinfo;    mp_get_buffer_raise(buffer_io, &bufinfo, MP_BUFFER_WRITE);
    mp_uint_t count = bufinfo.len;    if(count < 1) {        mp_raise_ValueError(NULL);    }
    // 32-bit kelimeleri oku ve sağlanan tampona ayrıştır    random_buffer(bufinfo.buf, count);
    return mp_const_none;}
MP_DEFINE_CONST_FUN_OBJ_0(pyb_rng_get_obj, pyb_rng_get);MP_DEFINE_CONST_FUN_OBJ_1(pyb_rng_get_bytes_obj, pyb_rng_get_bytes);

rng_get_or_fault() doğrudan STM32 RNG periferiklerini okur:

static uint32_t rng_get_or_fault(void){    // RNG periferisini henüz etkinleştirilmemişse etkinleştirin    rng_init();
    // Yeni bir rastgele sayının hazır olmasını bekleyin, yaklaşık 10us sürer    uint32_t start = HAL_GetTick();
    while (!(RNG->SR & RNG_SR_DRDY)) {        if (HAL_GetTick() - start >= RNG_TIMEOUT_MS) {            // donanım hatası... hiçbir şey döndürmeyin!            mp_raise_OSError(MP_EFAULT);        }    }
    // Yeni rastgele sayıyı alın ve döndürün    last_value = RNG->DR;
    return last_value;}

Bu, Coldcard özelleştirilmiş kodunun gerçekten donanım RNG kullanmak istediğini, ancak yalnızca pyb_rng_get* veya içsel random_buffer() çağrıldığında bu donanım işlevini garanti ettiğini gösterir.

Cüzdan oluşturulurken aslında aşağıdaki kod çağrılır, shared/seed.py dosyasındaki cüzdan oluşturma işlevi şudur:

async def make_new_wallet(nwords):    # Yeni rastgele bir tohum seçin.    await ux_dramatic_pause('Oluşturuluyor...', 3)    seed = generate_seed()    words = await approve_word_list(seed, nwords)    if words:        await commit_new_words(words)

Bu çağrı önce Coldcard'ın shared/random.py modülüne girer. Önceki sürümlerde, random.py doğrudan ngu.random'a bağımlıydı ve şunu koruyordu:

# random.py - uyumluluk olmadan, kripto kalitesinde rastgele sayı üreteci kullanan random modülünün alt kümesi# baytlar için ngu.random.byte(len) kullanın# bytes = ngu.random.bytes

Cüzdan başlatılması için random.bytes kullanılır, pyb.rng() değil; özelleştirilmiş pyb_rng_get_obj, random.bytes'i otomatik olarak geçersiz kılmaz.

MICROPY_HW_ENABLE_RNG 0 olarak ayarlandığı için cüzdan oluşturulurken donanım RNG kullanılmadı; bunun yerine micropython/ports/stm32/rng.c'deki pyb_rng_yasmarang çağrıldı:

#if MICROPY_HW_ENABLE_RNG
uint32_t rng_get(void) {    // STM32 donanımsal RNG kullanın    ...}
#else
// RNG'siz MCU'lar için hâlâ bir rng_get() fonksiyonu sağlamamız gerekir// Pseudo-RNG gerçekten ideal değil ancak şimdilik bunu kullanıyoruz.
// Yasmarang rastgele sayı üreticisistatic uint32_t pyb_rng_yasmarang(void) {    static bool seeded = false;    static uint32_t pad = 0, n = 0;    ...}
uint32_t rng_get(void) {    return pyb_rng_yasmarang();}
#endif

Pyb_rng_yasmarang, donanım cüzdan tohum üretimi için çok güvenli olmayan bir pseudo-rastgele sayı üretecidir ve saldırganlar brute force yöntemiyle anahtarı elde edebilir. Şu anda Coinkite, makefile dosyasında açıkça stm32/rng.c'yi hariç tutmuştur:

MicroPython'un yedek PRNG'sini derleme. Board'a özel rng.c, rng_get() sağlar ve bu boş nesne, üst akış nesne listesini karşılar.
$(BUILD)/rng.o: CFLAGS += -Dpyb_rng_yasmarang=error-do-not-want-this
$(BUILD)/rng.o:
$(ECHO) "SKIP stm32/rng.c"
$(Q)$(CC) $(CFLAGS) -x c -c /dev/null -o $@

İkinci: Çalınan fonların izlenmesi

Şu anda, birden fazla kurban cüzdanından fonlar aktarılmış ve toplanmış olup, birden fazla adrese yerleştirilmiş ve henüz daha fazla temizlenmemiştir. Beosin Trace, tehdit istihbaratı ve zincir üzerindeki davranış analizi yoluyla aşağıdaki toplama adreslerini tespit etmiştir:

bc1qq85v2c926eg6pgxhwp6q7lf6cnsz80qs3fcu9r (562 BTC)

https://wdcdn.qpic.cn/MTMxMDI3MDE1MTgxMDU0NzA_369595_usmImxZpHsKmu9X__1785899827?w=1080&h=656

bc1qx76cae2706qd5q576feh7xq8rfcsjpf2htfhe3 (398,47 BTC)

https://wdcdn.qpic.cn/MTMxMDI3MDE1MTgxMDU0NzA_304781_-IeWjFtIQ4RhvCbz_1785899827?w=1080&h=674

Ayrıca, yukarıdaki gibi bir fon akışı grafiğine sahip ve şu anda ek bir transfer bulunmayan aşağıdaki toplama adresleri de mevcuttur:

  • bc1q8jy96fe5lf8vfugydnte3cguk92gpev7kwtp3q (89,62 BTC)
  • bc1q0rvn88w08j75k4h48lf9fvhan7unjp7vjf5q6m (64,9 BTC)
  • bc1qtfrwa4j6rmj9rsgspv6a0yjumkg39js2numu75 (45,9 BTC)
  • bc1qmd5m5ktv7m5ffujxv4248fxv36myvdx79n8jp6 (30,18 BTC)

Coldcard cüzdanına yönelik saldırılar devam etmektedir; Beosin ekibi, daha fazla toplama adresini izlemekte ve ilgili fon akışlarını analiz etmektedir.

Üçüncü: Sonuç

Bu Coldcard donanım cüzdanının ciddi güvenlik olayı, geliştirme ekibinin rastgele sayı üretimi uygulamasındaki hata nedeniyle ortaya çıkmıştır; kritik cüzdan tohumu oluşturma aşamasında sahte rastgele sayı üretimi kullanılmıştır. Geliştirme ekibinin kodu sürekli ve kapsamlı şekilde test etmesi ve denetlemesi gerekir; Coldcard cüzdan kullanıcıları ise varlıklarını hemen taşımalı ve Coinkite'nin sonraki güvenlik duyurularını dikkatle takip etmelidir.

Beosin, projelerin başlatılmasından önceki akıllı sözleşme güvenlik denetimleri, projelerin çalışması sırasında güvenlik risklerinin izlenmesi ve engellenmesi, çalınan varlıkların geri kazanılması, sanal varlıkların para aklama (AML) önleme ve soruşturma takibi alanlarında uzmanlaşmış önde gelen bir blockchain güvenlik ve düzenleyici uyumluluk teknolojisi şirketidir. Beosin, dünya çapında 20'den fazla ülke ve bölgedeki düzenleyici ve uygulama kurumlarına, 200'den fazla sanal varlık hizmet sağlayıcısına ve 4.500'den fazla Web3 projesine “tek durakta” blockchain uyumluluk ürünleri ve güvenlik hizmetleri sunmaktadır.

Yasal Uyarı: Bu sayfadaki bilgiler üçüncü şahıslardan alınmış olabilir ve KuCoin'in görüşlerini veya fikirlerini yansıtmayabilir. Bu içerik, herhangi bir beyan veya garanti olmaksızın yalnızca genel bilgilendirme amacıyla sağlanmıştır ve finansal veya yatırım tavsiyesi olarak yorumlanamaz. KuCoin, herhangi bir hata veya eksiklikten veya bu bilgilerin kullanımından kaynaklanan sonuçtan sorumlu değildir. Dijital varlıklara yapılan yatırımlar riskli olabilir. Lütfen bir ürünün risklerini ve risk toleransınızı kendi finansal koşullarınıza göre dikkatlice değerlendirin. Daha fazla bilgi için lütfen Kullanım Koşullarımıza ve Risk Açıklamamıza bakınız.