6 Eylül 2026’da Liquid Network, gizli işlemlerin doğrulanmasında kullanılan Elements kod tabanındaki bir güvenlik açığı üzerinden saldırıya uğradı.
Sorun, rangeproof doğrulanırken önbellek anahtarının belirsiz biçimde oluşturulmasından kaynaklandı; rangeproof, bir işlemin gizli tutarının kabul edilebilir olduğunu doğrulayan kriptografik kanıttır. Bu nedenle iki farklı doğrulama verisi kümesi aynı önbellek kaydının oluşmasına yol açabiliyordu.
Saldırgan önce özel işlemler hazırlayıp önbelleği bunlarla doldurdu, ardından ihraç edilen varlık hacmini artıran kötü amaçlı bir işlem gönderdi: bu işlem, kaydedilmiş bir doğrulama sonucunu yeniden kullandı ve yetkisiz L-BTC üretilmesine imkân verdi.
Saldırgan bunun ardından bu varlıkları Liquid ağı içinde, Bitcoin ana ağına fon çıkarma mekanizması aracılığıyla gerçek bitcoin’lere çevirdi.
Arka plan
Liquid federasyonunun kontrolündeki özel bir Bitcoin cüzdanında kilitlenen bitcoin’ler, Liquid’de ihraç edilen L-BTC’nin karşılığını oluşturur. Öngörülen sabitleme (peg) sistemine göre bir L-BTC, federasyonun kontrolündeki bir BTC’ye karşılık gelmelidir.
İşlem, tutarı yayımlamak yerine bir Pedersen kriptografik taahhüdü içerebilir. Varlığın kendisi de benzer bir taahhütle temsil edilebilir. Özel bir matematiksel denklem işlemin giren ve çıkan değerlerinin dengeli olduğunu doğrular; rangeproof adı verilen kanıt ise her gizli tutarın izin verilen negatif olmayan aralıkta bulunduğunu gösterir.
Özellikle rangeproof doğrulaması, gizli tutarın gerçekten doğru olduğunu ve izin verilen miktarın üzerinde varlık üretmek için kullanılamayacağını güvence altına alması gereken mekanizmanın bir parçasıdır. Bununla birlikte doğruluğun fiilen denetlenmesi aynı anda birkaç unsura bağlıdır: rangeproof, değer taahhüdü, varlık taahhüdü ve scriptPubKey.
Betik, kriptografik doğrulamaya dahil edilen ek veri olarak secp256k1_rangeproof_verify fonksiyonuna aktarılır. Bir (C, X, S) kombinasyonu için geçerli olan bir kanıt, başka bir kombinasyon için otomatik olarak geçerli hâle gelmez.
Kilit işlemler
| Tarih/saat | TXID | Açıklama |
|---|---|---|
| 2026-09-06 13:52:10 | 271147100a94f6337b6c3db39b30c92d5b97ed91597307b6f721f73a15187ec5 | Hazırlık işlemi |
| 2026-09-06 13:53:10 | f24a4b179b5cc7e88b25a763911f7cbdf2bf45d1d1b5ab611e94461cef0a183f | Liquid içinde ek L-BTC hacmi yaratan işlem |
| 2026-09-06 13:54:10 | 3875a6d6ed4af708e6fd90d1c5504dc014e52c7093a566987252006d6cf1146b | İşlem, saldırganın ya da sıradaki cüzdanın kontrolündeki yeni gizli Liquid çıktıları oluşturuyor |
| 2026-09-06 14:00:10 | c6ea588ac26f5838b6acbb2a444a33b325bbfeb39bf16dfe27b47215ffd72267 | İşlem, saldırganın ya da sıradaki cüzdanın kontrolündeki yeni gizli Liquid çıktıları oluşturuyor |
| 2026-09-06 14:01:10 | 46f117c990580501a5156937a8c8affda551a38b3c0b99d29eb8469ee6beb3d2 | Liquid’den 2.65138358 L-BTC tutarında çıkış |
| 2026-09-06 14:06:10 | ce4caece413cd9d444ce7ed9f54e5b328b3da5e4af301aff59a3571f76e988f2 | Liquid’den 3,996.01834922 L-BTC tutarında çıkış |
| 2026-09-06 14:28:56 | 85d2ca15bea33a592e73ed40c6a5da887feecf1e77f58ec7f580e00841645043 | 3,996.01834922 BTC, bc1ql4mfu6aundtkksxklfajs2h3t9nzcd6gyqjlte adresine gönderildi |
| 2026-09-07 18:09:25 | a6d697a25266ce3c78774fd1d75f896b7af522ada209b0f6228ea497bc49a46d | 3,400 BTC, bc1qdlld6antmv4xug242ed83q7k4rqw50cwfns38szx4qu2f4jwaxxsuhwxxr adresine geri gönderildi |
Kilit adresler
| Adres | İşlevi |
|---|---|
| ex1q7kgx4ptje7px48tn0nsmc6se5pngdp3smpqa2w | Saldırganın Liquid ağındaki adresi |
| bc1qgslsydz56d0ed6827hdemfmk5w2f6ldyc6wt7p | Federasyonun 3,996.01834922 BTC’lik ödemesinin alıcısı |
| bc1ql4mfu6aundtkksxklfajs2h3t9nzcd6gyqjlte | Federasyonun 2.65138358 BTC’lik ödemesinin alıcısı |
| bc1ql4mfu6aundtkksxklfajs2h3t9nzcd6gyqjlte | Saldırganın fonları birleştirmek ve blok zincirinde mesaj iletmek için kullandığı adres |
| bc1qdlld6antmv4xug242ed83q7k4rqw50cwfns38szx4qu2f4jwaxxsuhwxxr | Liquid federasyonunun sabitleme ve fon çıkışı için kullandığı Bitcoin cüzdanı |
1. Kanıt önbelleğinin taklit edilmesi
Analiz için yalnızca blok zinciri gezgininin gösterdiği alanlar değil, Elements’in ham serileştirme verileri elde edilip ayrıştırıldı. İki hazırlık işleminin :0 çıktıları varlık, değer taahhüdü, nonce, betik, surjection proof ve rangeproof bakımından tamamen örtüşüyor.
Sıfırdan başlayan kaymalar ve aralığa dahil edilmeyen bir üst sınır kullanılarak, ham işlemin 8,882 baytından 271147100a94f6337b6c3db39b30c92d5b97ed91597307b6f721f73a15187ec5 işleminin output_0 alanı çözümlendi ve şu veriler elde edildi:
a. C0 = 09d6c6150e95e576d288dcc890bf48518119c6f227ea1be6f9a932792dbee683f5
b. S0 = 6a|43|086f5d67160fc4b477954fb09ef321e5b589d7a07740a1a6df494ed2335b1d01d8|0a0a488 de4899d0ae757f6cf8368663184d164106111ed9eaecf510e35282ddc6d|6a.
i. 6a, OP_RETURN anlamına gelir. ii. 43, sonrasında 67 baytın yerleştirilmesi gerektiğini belirtir.
Bu 67 bayt kasıtlı olarak şu yapıya sahiptir: 33 baytlık C1, 33 baytlık X ve tek baytlık 6a. Böylece betik S0 = 6a43 || C1 || X || 6a olur; burada X = 0a0a488de4899d0ae757f6cf8368663184d164106111ed9eaecf510e35282ddc6d, secp256k1_generator_generate(L-BTC asset ID) çağrısının sonucudur.
2. Etkin mempool’da önbelleğin doldurulması
Blok bağlanırken, mevcut kaydın tüketildiği ancak kayıt yoksa yenisinin saklanmadığı önbellek kuralları geçerlidir. Bu nedenle 4,050,335 numaralı bloğun bağlanması, iki görünür hazırlık işleminin ilk kabul edildiği anda oluşan önbellek kaydını silmiş olmalıydı.
Dolayısıyla ek L-BTC üreten işlemin, 4,050,335 numaralı blok bağlandıktan sonra ve hatalı çıktı denetlenmeden önce doğrulamayı geçebilmesi için, işlemi kabul eden her düğümde aynı (P0, C0, X, S0) dizisine sahip yeni ve geçerli bir işlem gerekiyordu.
Bu doldurma işleminin kimliği ve özgün baytları şimdilik bilinmiyor. Bunları bulmak için functionaries’ten birinin debug.log dosyası, o an geçerli olan mempool.dat, düğümler arasındaki veri alışverişinin kaydı ya da mempool durumunun saklanmış bir kopyası gerekebilir.
3. Liquid içinde ek L-BTC üretimi
f24a4b179b5cc7e88b25a763911f7cbdf2bf45d1d1b5ab611e94461cef0a183f enflasyon işleminin output_1 alanının çözümlenmesi şu verileri verdi:
a. C1 = 086f5d67160fc4b477954fb09ef321e5b589d7a07740a1a6df494ed2335b1d01d8.
Bu, hazırlık çıktısının OP_RETURN betiği tarafından aktarılan verinin tam olarak ilk 33 baytıdır.
Rangeproof P1’in P0’dan 68 bayt daha uzun olduğunu ve bu ek verinin sonda yer aldığını belirtmek gerekir: 09d6c6150e95e576d288dcc890bf48518119c6f227ea1be6f9a932792dbee683f5
b. 0a0a488de4899d0ae757f6cf8368663184d164106111ed9eaecf510e35282ddc6d6a43, bu da hazırlık işlemindeki C0’ı verir: 09d6c6150e95e576d288dcc890bf48518119c6f227ea1be6f9a932792dbee683f5
X = 0a0a488de4899d0ae757f6cf8368663184d164106111ed9eaecf510e35282ddc6d ise secp256k1_generator_generate(L-BTC asset ID) çağrısının sonucudur. Tam L-BTC üretecinin gömülmesi, hazırlık işleminin betik baytlarının saldırı işlemindeki varlık üreteci alanıyla hizalanmasına imkân verdi.
c. Genel olarak
Geçerli hazırlık işlemi: P0 || C0 || X || (6a43 || C1 || X || 6a)
Geçersiz saldırı işlemi: (P0 || C0 || X || 6a43) || C1 || X || 6a
İkisi de sonunda aynı 4,301 baytlık akışa indirgeniyor: P0 || C0 || X || 6a43 || C1 || X || 6a
4. Fonların çıkarılması
L-BTC, Liquid federasyonunun kontrolündeki gerçek BTC’ye geri çevrilebilir. Sıradaki 3875a6d6…f1146b işlemi, saldırıyla bağlantılı işlemin f24…:0 çıktısını kullandı. İki işlem daha, Bitcoin ana ağına fon çıkarmak için açık çıktılar oluşturdu:
- 46f117c9…eb3d2: 2.65138358 L-BTC
- ce4caece…988f2: 3,996.01834922 L-BTC
965,783 numaralı blokta onaylanan 8db751a6…7b140 Bitcoin işlemi, saldırı sonucunda çıkarılan iki tutarı tam olarak ödedi.
Güvenlik açığının özü neydi?
Elements, aynı pahalı kriptografik işlemi yeniden yapmamak için başarıyla doğrulanmış rangeproof’ları önbelleğe alır. Burada iki tasarım önemlidir.
Bu tasarım, ikisi de kanıtın geçerliliğini etkilemesine karşın varlık üretecini ve betiği hesaba katmıyordu. c26d719 commit’i, önbellek kaydını doğrulamanın tüm bağlamıyla ilişkilendirmeye çalıştı.
Önbellek uygulamasını içeren yama
Geçerli hazırlık işlemi: (P0, C0, X, 6a43 || C1 || X || 6a)
Geçersiz saldırı işlemi: (P0 || C0 || X || 6a43, C1, X, 6a)
Hazırlık ve saldırı işlemlerinin gözlemlenen çıktıları, daha eski P || C anahtarı kullanıldığında çakışma yaratmıyor. Eski anahtar için girdi verileri hem uzunluk hem de içerik bakımından farklı.
Saldırının kurgusu ise bu düzeltmeyle getirilen, ayırıcısı olmayan dört alanlı anahtara tam olarak uyuyor. Bu nedenle işlemin başarıyla geçmesi, c26d719’a benzer bir uygulamanın önceden doldurulmuş bir önbellekle birleştiğine işaret ediyor. Bununla birlikte Liquid’in ayrı functionary düğümlerinde çalıştırılan ikili dosyaların tam sürümleri kamuya açıklanmadı.
Senkronizasyon sorunu: Verus protokolü blockchain’ler arasındaki farklar yüzünden $7.5M’ı nasıl kaybettiFonların hareketi
Kendini «white hat» ilan eden kişi, değeri $268M olan 3,400 BTC’yi geri verdi ve güvenlik açığını bulma ödülü olarak $47M değerindeki 598.5 BTC’yi - toplamın %15’ini - kendisine ayırdı.
Adres: bc1ql4mfu6aundtkksxklfajs2h3t9nzcd6gyqjlte.
