Back to Blog

Haftalık Web3 Güvenlik Olayları Özeti | 30 Mar – 5 Nis 2026

Code Auditing
April 8, 2026
29 min read
Key Insights

Geçtiğimiz hafta (2026/03/30 - 2026/04/05), BlockSec dokuz saldırı olayını tespit edip analiz etti; toplam tahmini kayıp yaklaşık $287M olarak gerçekleşti. Aşağıdaki tablo bu olayları özetlemekte olup her bir olaya ilişkin ayrıntılı analizler sonraki alt bölümlerde sunulmaktadır.

Tarih Olay Tür Tahmini Kayıp
2026/03/30 Bilinmeyen Protokol Olayı Hatalı iş mantığı ~$10K
2026/03/30 WDGG Token Olayı Erişim kontrolü ~$40K
2026/03/31 i6Token Olayı Hatalı iş mantığı ~$273,8K
2026/04/01 Drift Protocol Olayı Kimlik avı saldırısı ~$285,3M
2026/04/01 LML Staking Protokol Olayı Hatalı iş mantığı ~$950K
2026/04/01 Tactile Olayı Fiyat manipülasyonu ~$12K
2026/04/02 SAS Token Olayı Hatalı iş mantığı ~$12K
2026/04/03 Bilinmeyen-EIP-7702 Olayı Erişim kontrolü ~$17,2K
2026/04/03 Silo Finance Olayı Yanlış yapılandırma ~$359K

Best Security Auditor for Web3

Validate design, code, and business logic before launch

1. Bilinmeyen Protokol Olayı

Kısa Özet

30 Mart 2026'da BNB Chain üzerindeki bilinmeyen bir protokol, hatalı iş mantığı nedeniyle yaklaşık $10K kaybetti. Protokol, kullanıcı yatırımlarının bir bölümünü platform tokeni olan PSTART satın almak ve likidite eklemek için kullanıyordu; bu durum, kullanıcıların piyasa fiyatı dalgalanmalarına maruz kalan LP pozisyonlarında fiilen pay sahibi olduğu anlamına geliyordu. Ancak para çekme işleminde protokol, o andaki gerçek LP itfa değerine göre hesaplama yapmıyordu. Bunun yerine geçmiş yatırım miktarına ve önceden tanımlanmış kurallara dayanarak sabit miktarda stablecoin ödemeyi vaat etmeye devam ediyordu. Bunun sonucunda saldırgan, zorunlu yatırım yoluyla sermaye taahhüt ettikten sonra önceden kararlaştırılmış sabit değer üzerinden para çekebildi; bu sayede LP pozisyonunun taşıması gereken kayıpları etkin biçimde protokole yıktı ve nihayetinde sıfır maliyetle kâr elde etti.

Arka Plan

Protokol şu şekilde işlemektedir: Kullanıcı BUSD yatırdıktan sonra protokol, likiditeye eklenecek nihai token ile BUSD oranının havuzun mevcut oranıyla daha iyi örtüşmesi için fonların bir bölümünü otomatik olarak PSTART satın almak için kullanır ve kalan BUSD ile birleştirerek havuza likidite ekler. Elde edilen LP payları Vault tarafından emanette tutulurken protokol iç muhasebesinde kullanıcı için sabit günlük getiri vaat eden bir emir kaydeder.

Bunun ardından kullanıcı sabit faiz oranıyla ödül talep edebilir; çıkış yaparken Vault, anapara ve getiriyi önceden tanımlanmış kurallara göre hesaplar; mevcut gerçek net varlık değerine göre itfa yapmaz.

Güvenlik Açığı Analizi

Bu güvenlik açığı, makul olmayan bir protokol (0x587984...73a43c) tasarımından kaynaklanmaktadır: hesaplama mantığı, temel varlıkların gerçek değerinden kopuktur.

Kullanıcı BUSD yatırdıktan sonra protokol, bir kısmını PSTART almak ve likidite eklemek için kullanır; bu da kullanıcının gerçek pozisyonunun piyasa fiyatlarıyla dalgalanan bir LP maruziyeti olduğu anlamına gelir. Ancak kullanıcı çıkış yaptığında protokol, o andaki gerçek LP itfa değerine göre değil, geçmiş yatırım miktarına ve önceden tanımlanmış kurallara dayanan sabit miktarda stablecoin ödemeyi vaat eder.

Saldırgan bu açığı büyük miktarda sermaye elde etmek için flaş kredi kullanarak ve ardından deposit() fonksiyonunu tekrar tekrar çağırarak istismar etti. Bunu yaparken protokolü sürekli PSTART almaya ve havuzun varlık kompozisyonunu değiştirmeye zorladı; böylece PSTART fiyatını yapay olarak artırarak arbitraj fırsatı yarattı.

Saldırgan ardından withdraw() fonksiyonunu çağırdı ve önceden vaat edilen sabit değer üzerinden para çekti; bu sayede pozisyonun taşıması gereken kayıpları protokole yıktı ve nihayetinde sıfır maliyetle kâr elde etti.

Saldırı Analizi

Aşağıdaki analiz, 0xf3b8...55e7 işlemine dayanmaktadır.

  • Adım 1: Saldırgan, flaş kredi aracılığıyla yaklaşık 2.000.000e18 BUSD elde etti ve havuzda 19.013.120e18 PSTART karşılığında takas yaptı.

  • Adım 2: Saldırgan, kontrattaki deposit() fonksiyonunu tekrar tekrar çağırarak fon stake etti. Her yatırımda protokol, likidite eklemek için kullanılan nihai token/BUSD oranının havuzun mevcut oranıyla daha iyi örtüşmesi için ne kadar BUSD ile token alınması gerektiğini hesapladı. Tekrarlanan yatırımlarla saldırgan havuza sürekli BUSD enjekte etti; PSTART miktarı ise neredeyse değişmedi. Sonuç olarak PSTART değeri sürekli yükseldi. Bu aşamada saldırganın yatırımları aracılığıyla elde edilen LP aslında zarar edilerek alınıyordu.

  • Adım 3: Saldırgan, 1. Adımda satın aldığı PSTART'ı havuza geri sattı. 2. Adım havuzun BUSD rezervlerini artırdığından bu takas yaklaşık 2.010.655e18 BUSD getirdi ve tek bir saldırı döngüsünde yaklaşık 10.655 BUSD kâr sağladı.

  • Adım 4: Son olarak saldırgan, 2. Adımda açılan tüm stake pozisyonlarında withdraw() fonksiyonunu çalıştırdı. Bu noktada söz konusu pozisyonlara karşılık gelen varlıkların piyasa değeri başlangıç yatırım değerinin çok altındaydı. Normal ekonomik mantıkla tam itfa mümkün olmamalıydı. Ancak protokol, itfa edilebilir BUSD miktarını geçmiş yatırım miktarına göre hesapladı; bu sayede saldırgan önceki zorunlu yatırım maliyetlerini herhangi bir kayba uğramadan tamamen geri kazandı.

Sonuç

Bu olayın temel nedeni, protokolün kullanıcı fonlarını piyasa fiyatı dalgalanmalarına maruz kalan LP pozisyonlarına yatırması, ancak yine de geçmiş yatırım değerlerine ve önceden tanımlanmış kurallara dayanan sabit miktarda BUSD ödemeyi taahhüt etmesidir. Bu durum, protokolün yükümlülükleri ile temel varlıklarının gerçek değeri arasında bir kopukluk yaratmıştır.

Saldırgan bu açığı, havuzun varlık yapısını değiştirmek ve PSTART fiyatını yukarı çekmek için deposit() fonksiyonunu tekrar tekrar kullanarak, ardından harici bir pozisyon aracılığıyla arbitrajı tamamlayarak ve son olarak withdraw() ile daha önce zarar eden pozisyonları defter değeri üzerinden itfa ederek istismar etti. Böylece pozisyonların taşıması gereken kayıplar protokole yıkıldı ve nihayetinde risksiz kâr elde edildi.


Get Started with Phalcon Explorer

Dive into Transactions to Act Wisely

Try now for free

2. WDGG Token Olayı

Kısa Özet

30 Mart 2026'da BNB Chain üzerindeki WDGG tokeni istismar edildi ve yaklaşık $40K kayıp yaşandı. Temel neden, burnFrom() fonksiyonundaki eksik erişim kontrolüydü. Özellikle burnFrom() fonksiyonu, rastgele kullanıcıların herhangi bir adresten WDGG tokenlerini yakmasına izin veriyordu. Saldırgan, PancakeSwap havuzundan WDGG tokenlerini yakarak bu açığı istismar etti; ardından sync() fonksiyonunu çağırarak havuzun WDGG rezervlerini azalttı ve akabinde ters takas gerçekleştirerek kâr elde etti.

Arka Plan

Bu olay, her transferde ücret tahsil eden temettü dağıtan bir token olan tek bir token, WDGG, ile ilgilidir.

Güvenlik Açığı Analizi

WDGG token kontratı (0x512de7...6b90c5), burnFrom() fonksiyonunu herhangi bir arayan yetkilendirmesi olmaksızın açığa çıkardı. Sonuç olarak herhangi bir adres, PancakeSwap havuzunun kendisi dahil herhangi bir sahipten WDGG tokenlerini yakabiliyordu. PancakeSwap'ın, kaydedilen rezervleri gerçek bakiyelerle hizalayan ve herkese açık şekilde çağrılabilen sync() fonksiyonuyla birleşince bu açık, havuzun WDGG rezervinin hiçbir meşru işlem yapılmadan keyfi olarak azaltılmasına ve sabit çarpım değişmezinin bozulmasına izin verdi; bu durum havuzu fiyat dengesizliği arbitrajına açık hale getirdi.

setWdgAddress() fonksiyonundaki ikincil bir açık, herhangi bir arayanın keyfi bir adresi ücretten muaf olarak işaretlemesine izin verdi ve bu saldırı yüzeyi aracılığıyla elde edilebilecek kârı daha da artırdı.

Saldırı Analizi

Aşağıdaki analiz, 0x2da5...0bd1 işlemine dayanmaktadır.

  • Adım 1: Saldırgan önce kendi adresini ücretten muaf olarak ayarlamak için setWdgAddress() fonksiyonunu çağırdı; bu sayede sonraki transferlerde tokenin transfer ücretini atlatabildi.
  • Adım 2: Saldırgan ardından PancakeSwap havuzu aracılığıyla az miktarda BNB'yi WDGG tokenleriyle takas etti.

  • Adım 3: WDGG elde ettikten sonra saldırgan, burnFrom() fonksiyonunu çağırarak PancakeSwap çift adresinden doğrudan WDGG tokenlerini yaktı.

  • Adım 4: Saldırgan akabinde sync() fonksiyonunu çağırarak çifti rezervlerini manipüle edilmiş token bakiyeleriyle eşleşecek şekilde güncellemeye zorladı. Sonuç olarak havuzdaki WDGG rezervi yalnızca 1 wei'ye indirildi.

  • Adım 5: Havuz rezervleri ciddi ölçüde bozulunca saldırgan ters takas gerçekleştirdi ve fiyat dengesizliğinden kâr elde etti.

Sonuç

Bu olay nihayetinde WDGG token kontratındaki burnFrom() fonksiyonundaki eksik erişim kontrolünden kaynaklandı. Bunun sonucunda saldırgan, tokenleri doğrudan PancakeSwap havuzundan yakabildi, havuzun rezervlerini sync() aracılığıyla manipüle edebildi ve oluşan fiyat dengesizliğinden kâr elde etti.


3. i6Token Olayı

Kısa Özet

31 Mart 2026'da BNB Chain üzerindeki i6 Tokeni, invest() fonksiyonunun havuzun anlık fiyatını hareket ettirmesi ancak withdraw() fonksiyonunun bakiyeleri gecikmeli bir TWAP üzerinden hesaplaması ve ikisinin aynı işlemde birleştirilebilmesi nedeniyle yaklaşık $273,8K kaybetti. Saldırgan, invest() aracılığıyla anlık fiyatı şişirdi, withdraw() fonksiyonu aracılığıyla eski TWAP fiyatından fazladan i6 itfa etti ve i6'yı şişirilmiş havuza geri satarak kâr elde etti.

Arka Plan

Protokol şu şekilde işlemektedir. Kullanıcı invest() fonksiyonunu çağırdığında USDT yatırılır ve bir bölümü PancakeSwap'ta i6 satın almak için kullanılır. Elde edilen i6, kalan USDT ile birlikte USDT/i6 havuzuna likidite olarak eklenir ve ortaya çıkan LP tokenleri yakılır. Protokol, kullanıcı ve yönlendirici bakiyelerini USDT cinsinden kaydeder.

withdraw() fonksiyonu çağrıldığında protokol, kullanıcının birikmiş değerini USDT cinsinden hesaplar ve protokolün tuttuğu TWAP fiyatı (twapPrice) kullanılarak i6'ya dönüştürür.

Güvenlik Açığı Analizi

Protokol kontratındaki (0x1cb36b...2a18a) temel neden şudur: invest(), i6 satın alma ve likidite eklemenin yan etkisi olarak USDT/i6 havuzunun anlık fiyatını değiştirirken withdraw(), birikmiş USDT cinsinden bakiyeleri yalnızca zaman penceresi geçtikten sonra güncellenen protokol tarafından tutulan bir TWAP (twapPrice) kullanarak i6'ya çevirir. Kontrat, bu iki fonksiyonun aynı işlemde çalışmasını engelleyen herhangi bir mekanizma içermez.

Bir invest() çağrısı, sonraki bir withdraw() fonksiyonunun henüz güncellenmemiş bir TWAP okuduğu aynı işlem içinde anlık fiyatı şişirebildiğinden ikisi aynı havuz durumu için iki farklı fiyat görür. withdraw() aracılığıyla itfa edilen USDT cinsinden bakiye, her i6 aslında havuzda çok daha fazla USDT karşılığı itfa edilebilir durumdayken eski, çok daha düşük fiyattan i6 olarak ödenir. Bu boşluk, protokoldeki birikmiş tüm USDT bakiyesini iç hesaplama ile canlı havuz arasındaki işletilebilir bir spreada dönüştürür.

Saldırı Analizi

Aşağıdaki analiz, 0xc1b9...2f16 işlemine dayanmaktadır.

  • Adım 1: Saldırgan önce flaş kredi aracılığıyla 270.000 WBNB elde etti, ardından Venus'e teminat olarak sağladı ve büyük miktarda USDT borç aldı. Saldırgan ayrıca 0xda49 adresinde saldırı kontratı A'yı ve 0x096a adresinde yardımcı kontrat B'yi konuşlandırdı.

  • Adım 2: Saldırı kontratı ilk invest() fonksiyonunu çalıştırdı. Bu süreçte protokol önce 531.489e18 USDT kullanarak 234.188e18 i6 satın aldı ve ardından 354.326e18 USDT ile 72.607e18 i6'yı birlikte havuza ekledi. Sonuç olarak havuz anlık fiyatı yaklaşık 1,05159 USDT/i6'dan yaklaşık 4,89287 USDT/i6'ya hızla yükselirken protokolün kaydettiği TWAP yalnızca 1,05159'da kalmaya devam etti.

  • Adım 3: Saldırgan ardından 124.014.184e18 USDT'yi yardımcı kontrat B'ye aktardı; bu kontrat da referrer = A olarak invest() fonksiyonunu çağırdı. Bu adım, protokolü bir kez daha büyük çaplı USDT -> i6 alımı ve addLiquidity() işlemi yapmaya zorladı; havuz rezervleri yaklaşık 15.528 USDT/i6 anlık fiyatına karşılık gelen yeni bir duruma taşındı. Ancak yeni bir zaman penceresi geçmediğinden protokol TWAP'ı buna göre güncellemedi.

  • Adım 4: İkinci invest() tamamlandıktan sonra yönlendirici olarak saldırı kontratı A, USDT cinsinden bir yönlendirme ödülüne hemen hak kazandı. Saldırgan ardından withdraw() fonksiyonunu çağırdı. Protokol, ödenecek i6 miktarını hesaplamak için eski TWAP'ı kullandı ve tokenleri kendi bakiyesinden aktardı; toplam ödeme 5.896.508e18 i6 oldu.

  • Adım 5: i6'yı aldıktan sonra saldırgan, tüm 5.896.508e18 i6'yı havuza geri satmak ve 125.177.224e18 USDT karşılığında takas yapmak için hemen swapExactTokensForTokensSupportingFeeOnTransferTokens() fonksiyonunu çağırdı. Bu i6 tokenleri yaklaşık 1,05159 USDT/i6 eski TWAP kullanılarak hesaplanmış, saldırgan tarafından yaklaşık 15.528 USDT/i6'ya çekilen havuz anlık fiyatına karşı satılmıştı; saldırgan iki fiyat arasındaki devasa spreadi doğrudan realize edebildi.

  • Adım 6: Flaş krediyi geri ödedikten sonra saldırgan, saldırıdan elde edilen gerçek kâr olan 273.802e18 USDT'yi elinde tuttu.

Sonuç

Temel neden, anlık fiyatı etkileyen bir fonksiyonun (invest()) ve TWAP'a göre hesap kapatan bir fonksiyonun (withdraw()) tek bir işlem içinde bir araya getirilebilmesi; bu sayede ikisinin aynı havuz durumu için farklı fiyatlar görmesidir.

Bu tür açıkları önlemek için, AMM etkileşimlerini gecikmeli fiyatlandırmayla birleştiren protokoller, eşlik eden bir fonksiyonun temel havuzun anlık fiyatını hareket ettirdiği aynı işlem içinde bakiyeleri bir TWAP üzerinden kapatmaktan kaçınmalı; ödemeleri eski veya türetilmiş bir fiyat yerine havuzun canlı gerçekleştirilebilir değerine dayandırmalıdır.


4. Drift Protocol Olayı

Kısa Özet

1 Nisan 2026'da (UTC) Solana üzerindeki Drift Protocol, yaklaşık $285,3M'lık bir saldırıya maruz kaldı. Temel neden bir akıllı kontrat hatası değil, sıfır zaman kilidine sahip 2/5 Güvenlik Konseyi ve Solana'nın kalıcı nonce mekanizmasıyla daha da karmaşık bir hal alan multisig yetkilendirme sürecindeki bir çöküştü; bu mekanizma önceden toplanmış multisig onaylarının saldırgan bunları çalıştırmayı seçene kadar süresiz geçerli kalmasına izin verdi. Haftalarca süren hazırlık aşamasının ardından saldırgan, beş imzacıdan ikisini kalıcı nonce hesaplarına bağlı kötü amaçlı yönetişim işlemlerini önceden imzalamaya yönlendirdi; bunları daha sonra yönetici kontrolünü ele geçirmek için gönderdi ve ardından sahte bir teminat varlığı (CVT) tanıttı, oracle fiyatını şişirdi, çekim limitlerini gevşetti ve Drift Vault (JCNCMF...XJfrw) aracılığıyla gerçek varlıkları drene etti.

Arka Plan

Drift Protocol, Solana üzerinde marjlı işlemleri, borç vermeyi, spot piyasaları ve türevleri destekleyen bir DeFi protokolüdür. Yönetici değişiklikleri, piyasa oluşturma, oracle yapılandırması, risk parametresi güncellemeleri ve çekim limiti ayarlamaları dahil yüksek ayrıcalıklı operasyonlar, tek bir özel anahtar yerine Squads multisig çerçevesi tarafından yönetilmektedir. Saldırı sırasında Drift'in Güvenlik Konseyi, sıfır zaman kilitiyle 2/5 eşik yapılandırması altında çalışıyordu; bu da beş imzacıdan herhangi ikisinin idari eylemleri anında yetkilendirebileceği anlamına geliyordu. Bu sistemin güvenliği yalnızca imzacı anahtar güvenliğine değil, tam onay hattının bütünlüğüne de bağlıdır: hangi işlemin oluşturulduğu, imzacıların neyi onayladıklarına inandıkları ve nihayetinde çalıştırılan talimatların bu inceleme bağlamıyla örtüşüp örtüşmediği.

Ayrıca Solana'nın kalıcı nonce hesapları, kısa ömürlü blockhash'in yerine özel bir hesapta saklanan kalıcı bir nonce koyar; bu sayede imzalanmış bir işlem, nonce ilerletilene kadar süresiz geçerli kalabilir. Bu mekanizma, çevrimdışı imzalama ve gecikmeli gönderim gibi meşru kullanım durumları için tasarlanmıştır; ancak bir işlemin ne zaman imzalandığını ne zaman zincir üzerinde çalıştırıldığından ayırarak kritik bir saldırı primitifi sunar. Bir imzacı kalıcı nonce işlemini onayladıktan sonra, nonce otoritesi nonce hesabını manuel olarak ilerletmedikçe onay iptal edilemez.

Güvenlik Açığı Analizi

Temel neden bir akıllı kontrat hatası değil, Drift'in yönetişim yapılandırmasındaki birlikte $285,3M'lık bir akışa zemin hazırlayan üç yapısal zayıflıktır. Birincisi, kalıcı nonce'lar örtük imza-sona erme güvenlik ağını ortadan kaldırdı. Normal blockhash tabanlı işlemlerde aldatılmış bir imzacının onayı ya hızlıca çalıştırılır ya da dar bir pencere içinde zararsız biçimde sona erer; bu da koordineli istismar kapsamını sınırlar. Kalıcı nonce'lar bu kısıtlamayı ortadan kaldırır: iki Güvenlik Konseyi imzacısı yanıltıcı imzalama talepleri aracılığıyla kötü amaçlı yönetişim işlemlerini onaylamaya yönlendirildikten sonra imzaları süresiz olarak istismar edilebilir hale geldi ve saldırgana yürütme zamanlaması üzerinde tam kontrol sağladı.

İkincisi, idari eylemler üzerindeki sıfır zaman kilidi, önceden imzalanmış işlemler gönderildikten sonra yönetici transferinin anında yürürlüğe girmesi anlamına geliyordu; tespit veya müdahale penceresi bırakmıyordu. Üçüncüsü, yönetici rolünün kapsamı tek bir ayrıcalıklı yol üzerinden yeni teminat piyasaları oluşturmaya, oracle kaynaklarını değiştirmeye ve çekim limitlerini gevşetmeye yetecek kadar genişti; dolayısıyla tek bir başarılı yönetişim ele geçirmesi, herhangi bir ek yetkilendirme engeli olmaksızın keyfi bir varlığı gerçek fon çıkarımına dönüştürmek için yeterliydi.

Saldırı Analizi

Saldırı üç farklı aşamada gerçekleşti: saldırganın sahte bir teminat varlığı oluşturmak ve yanıltıcı imzalama talepleri aracılığıyla yönetişim erişimi elde etmek için haftalarca süren bir operasyon yürüttüğü Saldırı Öncesi Hazırlık; yönetici kontrolünü ele geçirmek için iki önceden imzalanmış kalıcı nonce işleminin art arda gönderildiği Yönetişim Ele Geçirme; ve saldırganın protokol parametrelerini manipüle edip protokolün borç verme yolları aracılığıyla gerçek varlıkları drene ettiği Fon Çıkarımı. Aşağıdaki şema bu üç aşamadaki yürütme akışını göstermektedir.

  • Aşama 1 (Saldırı Öncesi Hazırlık): 11 Mart'tan itibaren saldırgan Tornado Cash'ten 10 ETH çekti ve CarbonVote Token (CVT) konuşlandırarak 750 milyon birim baskı yaptı; ardından Raydium'da likidite sağladı ve yapay fiyat geçmişini yaklaşık $1 civarında oluşturmak için yıkama ticareti kullandı. Bu süreçte 23 Mart'a kadar dört kalıcı nonce hesabı oluşturuldu; ikisi Drift Güvenlik Konseyi üyelerine, ikisi saldırganın kontrolündeki hesaplara bağlıydı; bu durum beş imzacıdan en az ikisinin kalıcı nonce hesaplarına bağlı işlemleri zaten imzaladığını gösteriyordu. 27 Mart'ta Drift, üye değişikliği nedeniyle planlı bir Güvenlik Konseyi geçişi gerçekleştirdi ve önceden toplanan imzaları geçersiz kıldı; ancak 30 Mart'a kadar saldırgan yeni yapılandırma altında gerekli eşiği yeniden elde etti; bu durum zincir üzeri yönetişim değişikliklerinin aktif olarak izlendiğini ve gerçek zamanlı uyum sağlandığını gösterdi.

  • Aşama 2 (Yönetişim Ele Geçirme): 1 Nisan'da yaklaşık 16:05 UTC'de, Drift'in sigorta fonundan meşru bir test çekimi gerçekleştirmesinden yaklaşık bir dakika sonra saldırgan, dört slot arayla iki önceden imzalanmış kalıcı nonce işlemi gönderdi. İlk işlem (2HvMSg...2C4H) kötü amaçlı yönetici transferi teklifini oluşturdu ve onayladı. İkinci işlem (4BKBmA...RsN1) bunu onaylayıp yürüttü; kaydedilen nonce'u etkinleştirmek için AdvanceNonceAccount ile başladı, proposalApprove ve vaultTransactionExecute aracılığıyla ilerledi ve nihayetinde idari kontrolü saldırganın kontrolündeki bir adrese devretmek için UpdateAdmin'i çağırdı.

  • Aşama 3 (Fon Çıkarımı): Tam yönetici ayrıcalıklarıyla saldırgan CVT için bir teminat piyasası oluşturdu, defter fiyatını şişirmek için saldırganın kontrolündeki bir oracle'a geçti ve önemli varlık piyasalarındaki çekim limitlerini artırdı veya kaldırdı. Saldırgan ardından protokole büyük miktarda aşırı değerlendirilmiş CVT yatırdı ve yaklaşık 12 dakika içinde 31 hızlı çekim gerçekleştirerek USDC, JLP, SOL, cbBTC, USDT, wETH, dSOL, WBTC, JTO ve FARTCOIN'i drene etti; saldırganın çekim hesabına (HkGz4K...pZES) göre toplam kayıp yaklaşık $285,3M olarak hesaplandı.

Sonuç

Bu olayın temel nedeni bir akıllı kontrat güvenlik açığı veya anahtar ele geçirilmesi değil, kalıcı nonce tabanlı gecikmeli yürütme ve sıfır zaman kilidi idari yoluyla birleşen multisig yetkilendirme sürecindeki bir çöküştür. Normalde dakikalar içinde sona erecek olan önceden toplanmış onaylar süresiz olarak istismar edilebilir hale geldi ve gönderildikten sonra yönetici ele geçirme ile ardından gelen fon çıkarımı herhangi bir müdahale penceresi bırakmadı.

Bu tür riskleri azaltmak, yalnızca imzacı anahtar güvenliğini değil tam yetkilendirme hattını güvence altına almayı, yüksek ayrıcalıklı operasyonlarda zaman kilidi uygulamayı ve kalıcı nonce gibi gecikmeli yürütme mekanizmalarını, daha yüksek imza eşiklerini, zaman sınırlı veya iptal edilebilir onayları ve süresiz geçerli imzalanmış işlemlere karşı kısıtlamaları gerektiren ayrı bir tehdit yüzeyi olarak ele almayı gerektirmektedir.


5. LML Staking Protokol Olayı

Kısa Özet

1 Nisan 2026'da BNB Chain üzerindeki LML staking protokolü yaklaşık $950K'lık bir saldırıya maruz kaldı. Temel neden, ödül hesaplama mantığındaki bir tutarsızlıktı: ödül dönüşümü 3600 saniyelik güncelleme bekleme süresiyle kilitlenmiş saklanan bir LML/USDT fiyatını okurken ödenen LML canlı AMM fiyatından itfa edilebilirdi; ikisi arasında sapma kontrolü yoktu. Saldırgan, havuz anlık fiyatını şişirmek için flaş kredi ve tek bir işlemde önceden stake edilmiş 11 EOA için toplu ödül talep etmek amacıyla EIP-7702 kod delegasyonunu kullanarak eski saklanan fiyattan aşırı miktarda LML aldı ve ciddi ölçüde bozulmuş havuz üzerinden geri satarak kâr elde etti.

Arka Plan

LML, kullanıcıların BNB'yi APower kontratı aracılığıyla stake ederek LML tokenleri ödül olarak kazandığı BNB Chain üzerinde bir staking protokolüdür. Ödüller USDT cinsinden hesaplanır, ardından dağıtımdan önce protokolde saklanan LML/USDT fiyatına göre LML miktarlarına dönüştürülür. Saklanan fiyat, AMM anlık fiyatını okuyan ancak güncellemeler arasında 3600 saniyelik bekleme süresi uygulayan updatePrice() tarafından yenilenir. Ödül talepleri APower'ın receive() fonksiyonu aracılığıyla msg.sender'a göre tetiklenir; bu nedenle yalnızca orijinal staking adresi kendi ödüllerini talep edebilir.

Güvenlik Açığı Analizi

Staking kontratındaki (0xbe9713...adce19) temel açık, ödül tahakkuku ve ödül itfasının ikisi arasında tutarlılık kontrolü olmaksızın aynı havuzun iki farklı fiyatına sabitlenmiş olmasıdır. reward += (10^18 * base_reward) / stored_price ödül formülü, LML ödemesini yalnızca 3600 saniyelik bekleme süresinin ardından updatePrice() tarafından yenilenen, protokolde saklanan LML/USDT fiyatı olan _prices[]'dan hesaplar; ancak ödenen LML canlı AMM anlık fiyatından anında itfa edilebilir. Bu bekleme penceresi içinde anlık fiyatı hareket ettiren herhangi bir harici faaliyet, dondurulmuş bir tahakkuk fiyatı ile canlı satış fiyatı arasında bir boşluk açar; kontrat bu boşluğun makul olmayan bir hal aldığında talebi reddeden herhangi bir mekanizma içermez.

İkinci bir yapısal açık, ödül kaynağının nasıl yenilendiğiyle ilgilidir. PROOF kontratının LML bakiyesi bir talebi karşılamaya yetmediğinde swapBack(), normal bir takas yerine doğrudan LP çiftinin rezervlerinden LML çıkaran ve çiftin saklanan durumunu yeniden hizalayan super._transfer(swapPair, PROOF, deficit) ve ardından sync() çağırarak onu yeniler. Bu yol çiftin fiyat keşfini atlatığından, bunu tetikleyen her talep çiftin LML rezervlerini herhangi bir dengeleyici token girişi olmaksızın azaltır ve anlık fiyatı daha da kaydırır; tekrarlanan talepler mekanik olarak dondurulmuş saklanan fiyat ile canlı satış fiyatı arasındaki boşluğu genişletir.

Saldırı Analizi

Aşağıdaki analiz, 0x805d...5b47 ve 0x70f7...3572 işlemlerine dayanmaktadır.

  • Adım 1: Saldırgan, Moolah'tan borç alarak (Venus ve Moolah Pool'dan WBNB teminatıyla), PancakeSwap V4'ten, birden fazla V3 havuzundan ve V2 havuzlarından flaş kredi kullanarak büyük miktarda USDT ve WBNB bir araya getirdi. Bu sermaye, LML/USDT çift fiyatını manipüle etmek için gerekliydi.

  • Adım 2: Saldırgan, LML token kontratında swapAndTrans() fonksiyonunu çağırarak kontratta biriken LML ücretlerini USDT'ye takas etti. Bu işlem LML kontratının kendi LML bakiyesini tüketti; yani artık yerel token kaynağı olarak hizmet veremezdi ve sonraki ödül dağıtımlarında swapBack() aracılığıyla LP çiftinden LML çekmesi gerekecekti.

  • Adım 3: Saldırgan, alıcı olarak ölü adres ayarlanmış şekilde PancakeRouter swapExactTokensForTokensSupportingFeeOnTransferTokens aracılığıyla USDT'yi LML'ye takas etti. Satın alınan LML tokenleri saldırgan tarafından alınmak yerine yakıldı. Tek amaç, çiftten LML drene etmek ve AMM'de LML fiyatını şişirmekti; saldırganın tokenlerin kendisine değil yalnızca fiyat bozulmasına ihtiyacı vardı.
  • Adım 4: Saldırgan, daha önce 11 EOA adresi kullanarak staking protokolüne yatırım yapmıştı. APower'ın receive() fonksiyonu msg.sender'a göre _claimReward(msg.sender) tetiklediğinden ödüller yalnızca yatırım adresi tarafından talep edilebilir. Tüm 11 EOA için tek bir işlemde ödül talep etmek amacıyla saldırgan, bu EOA'lara kod atamak için EIP-7702 kullandı ve bunların saldırganın ana kontratı tarafından kontrat olarak çağrılmasını sağladı. Her EOA, APower'a az miktarda BNB gönderen ve receive() ile _claimReward(EOA) tetikleyen bir transfer(rst, fte) fonksiyonu çalıştırdı. Her talep içinde: updatePrice() atlandı (3600 saniyelik bekleme süresi dolmadı, dolayısıyla stored_price tarihsel düşük değerde kaldı), updateUser() eski düşük fiyatı kullanarak ödülü hesapladı, sendMining() PROOF'tan APower'a LML aktardı ve ardından LP çiftinden LML çekerek PROOF'u yenileyen ve çiftin rezervlerini daha da azaltan sync() çağıran swapBack() tetikledi. Son olarak claimReward() EOA'ya LML dağıttı ve her EOA aldığı LML'yi saldırgan kontratına geri aktardı.
  • Adım 5: Saldırgan, biriken LML'yi aşırı şişirilmiş fiyat üzerinden şimdi ciddi ölçüde tüketilmiş havuz aracılığıyla USDT'ye geri takas etti.

  • Adım 6: Tüm flaş krediler, borçlar ve ücretler geri ödendi. Kalan kâr aktarıldı.

Sonuç

Temel neden, staking kontratındaki ödül tahakkuku ve itfası arasındaki uyumsuzluktur: ödemeler 3600 saniyelik bekleme süresinin arkasında kilitlenmiş saklanan LML/USDT fiyatından boyutlandırılır, ancak gerçek değeri canlı AMM fiyatını takip eden LML cinsinden kapatılır; ikisini birbirine bağlayan sapma kontrolü yoktur. swapBack() yenileme yolu, her talep işlenirken LP çiftinden doğrudan LML drene etmek suretiyle bu açığı daha da kötüleştirir; dondurulmuş saklanan fiyat ile canlı satış fiyatı arasındaki boşluğu mekanik olarak genişletir.

AMM'den türetilmiş fiyatlardan ödülleri boyutlandıran staking protokolleri, talep anında saklanan fiyat ile mevcut anlık fiyat arasında bir sapma kontrolü uygulamalı ve boşluk güvenli bir eşiği aştığında geri dönmelidir; ayrıca LP rezervlerini normal takas yolları dışında mutasyona uğratan yenileme mekanizmalarından kaçınmalıdır; zira bu tür mekanizmalar, eski fiyatlandırmadan kaynaklanan hasarı başka türlü sınırlayacak fiyat keşfini atlatır.


6. Tactile Olayı

Kısa Özet

1 Nisan 2026'da Polygon üzerindeki kademeli mevduat protokolü Tactile, yaklaşık $12K kayıp yaşadı. Temel neden, yatırım ve çekim hesaplama mantığındaki bir tutarsızlıktı: hem giriş hem çıkış, CES'in mevcut anlık fiyatına göre dönüştürülüyordu ve iç pay, ilk basıldığı varlık değerinin kaydını taşımıyordu. Saldırgan bunu, yatırım yapmadan önce anlık fiyatı şişirerek aşırı büyük pay elde ederek, ardından çekim yapmadan önce fiyatı düşürerek pay başına daha fazla CES itfa ederek ve kâr elde etmek için döngüyü yardımcı kontratlar arasında tekrarlayarak istismar etti.

Arka Plan

Tactile, kullanıcıların seçilen kademeye göre bir ödeme kontratına CES yatırdığı Polygon üzerinde kademeli bir mevduat protokolüdür. Gerekli mevduat miktarı, CES'in mevcut anlık fiyatından ve kademe yapılandırmasından hesaplanır; kullanıcıya pozisyonunu temsil eden iç muhasebe payı verilir. Çekimde, kaydedilen pay, ilk yatırılan miktara göre kapatılmak yerine çıkış anındaki anlık fiyat kullanılarak CES'e geri dönüştürülür; dolayısıyla kullanıcı bakiyeleri sabit varlık miktarları yerine fiyata bağımlı muhasebe birimleri olarak takip edilir.

Güvenlik Açığı Analizi

Ödeme kontratındaki (0x9153e1...09b654) temel açık, yatırım ve çekimin ikisini birbirine bağlayan değişmez bir çıpa olmaksızın iki farklı anda aynı anlık fiyat oracle'ına göre kapatılmasıdır. Yatırım anında kontrat getActualPrice() okur ve yatırılan CES'i mevcut fiyata göre iç paya dönüştürür; çekim anında aynı pay, itfa anındaki anlık fiyatı kullanılarak CES'e geri dönüştürülür.

Pay, basıldığı fiyat veya varlık miktarının kaydını taşımadığından bu iki an arasındaki herhangi bir anlık fiyat hareketi, ödenen CES ile alınan CES arasında doğrudan bir uyumsuzluğa dönüşür; protokolün muhasebesini temel varlık değeri yerine fiyat yoluna tam anlamıyla maruz bırakır.

Saldırı Analizi

Aşağıdaki analiz, 0xc321...da74 işlemine dayanmaktadır.

  • Adım 1: Saldırgan önce Uniswap V3 flaş havuzundan 55.365e18 CES ödünç aldı ve fonları 5 yardımcı kontrata dağıttı. Her yardımcı önce 6.426e18 CES aldı, ardından deposit(12) fonksiyonunu çağırdı. Bu süreçte her yardımcı önce getPriceForLevel(12) sorgusunu yaptı, ardından bu yatırım için mevcut fiyata göre gereken CES miktarını hazırladı.
  • Adım 2: Tüm 5 yardımcı ilk deposit turunu tamamladıktan sonra saldırgan, DEX'e 300.000 CES satarak bank'ın kullandığı fiyatı 1,067585'ten 0,688542'ye düşürdü. 5 yardımcı ardından withdraw işlemini birer birer gerçekleştirdi; daha önce yüksek fiyattan oluşturulan payları artık düşük fiyattan CES'e itfa etti. Her yardımcı 9.427e18 CES aldı.
  • Adım 3: İlk withdraw turunu tamamladıktan sonra saldırgan, elde edilen karşı taraf varlığını tekrar CES'e takas ederek fiyatı yeniden yukarı çekti. Ardından 2-3. adımları tekrarladı.

  • Adım 4: Son olarak birden fazla saldırı döngüsünün ardından ve 166,097975017841805126 CES flaş kredisi ile flaş ücretini geri ödedikten sonra saldırgan kâr olarak 567.736e18 CES elde etti.

Sonuç

Bu olayın temel nedeni, Tactile'ın hem yatırımı hem de çekimi manipüle edilebilir bir anlık fiyata göre hesaplaması ve muhasebe payını yatırım anındaki varlık miktarına veya fiyata sabitlememesidir; bu durum iç muhasebesini giriş ve çıkış arasındaki herhangi bir fiyat hareketine tam anlamıyla maruz bıraktı.

Uçucu bir varlığa karşı pay benzeri pozisyonlar düzenleyen protokoller, her payı basım anındaki somut varlık miktarına veya fiyata sabitlemelidir; böylece itfa, canlı oracle'a göre yeniden fiyatlandırmak yerine orijinal ekonomik değeri yeniden üretir. Hesaplama fonksiyonlarının mevcut fiyata başvurması gerektiğinde, zaman ağırlıklı veya başka şekilde manipülasyona dirençli kaynaklar kullanmalı ve hesaplama çağrısıyla aynı işlemde yürütülen işlemlerle hareket ettirilebilen aynı anlık fiyatı okumaktan kaçınmalıdırlar.


7. SAS Token Olayı

Kısa Özet

2 Nisan 2026'da BNB Chain üzerindeki SAS tokeni yaklaşık $12K'lık bir saldırıya maruz kaldı. Temel neden, tokenin özel transfer mantığındaki bir açıktı: LP havuzuna SAS göndermek yalnızca global sellBurn sayacını artırıyordu ve sonraki herhangi bir sıradan transfer, AMM'nin takas mantığından geçmeden SAS'ı doğrudan havuzdan yakabilir ve rezervlerini güncellemek için sync() çağırabiliyordu. Saldırgan bunu, satışlar yoluyla sellBurn biriktirerek, ilgisiz bir sıradan transferi havuzdan SAS yakmak ve rezervini 1 wei'ye indirmek için tetikleyerek ve ardından kalan SAS'ı kâr için ters takasla satarak istismar etti.

Arka Plan

SAS, PancakeSwap V2 havuzu üzerine inşa edilmiş özel transfer mantığına sahip BNB Chain üzerinde deflationary bir tokendir. transfer() fonksiyonu iki yol arasında ayrım yapar: transferin hedefi LP havuzu olduğunda tetiklenen satış yolu, aktarılan miktarı global sellBurn toplayıcısına ekler; sıradan transfer yolu ise sellBurn sıfır değilse SAS'ı doğrudan LP havuzundan yakar ve ardından rezervlerini yeni zincir üzeri bakiyeye güncellemek için sync() çağırır. İki yol, birikimli satış baskısına yanıt olarak havuzun SAS rezervini azaltan deflationary bir mekanizma olarak birlikte çalışmak üzere tasarlanmıştır.

Güvenlik Açığı Analizi

SAS token kontratındaki (0xbfa266...3d91c6) temel açık, deflationary mekanizmanın transfer() fonksiyonuna nasıl bağlandığıyla ilgilidir. SAS LP havuzuna gönderildiğinde kontrat, global sellBurn toplayıcısını aktarılan miktarla artırır. Ardından herhangi bir sonraki sıradan transferde, sellBurn sıfır değilse kontrat _burnFromPair() çağırarak LP havuzundan doğrudan SAS yakar ve ardından havuzun rezervlerini zincir üzeri bakiyesiyle eşleştirmek için sync() çağırır.

Sorun şu ki bu yak-ve-senkronize yolu, AMM'nin takas mantığından geçmeden havuzun rezervlerini yeniden yazar. Havuza yapılan transferler yoluyla sellBurn artırıldıktan sonra, ilgisiz bir normal transfer yakmayı ve senkronizasyonu tetiklemeye yeterlidir; havuzun SAS rezervini sıfıra yaklaştırır ve ardından normal bir takas yoluyla hasat edilebilecek büyük bir fiyat bozulması yaratır.

Saldırı Analizi

Aşağıdaki analiz, 0x878e...adc5 işlemine dayanmaktadır.

  • Adım 1: Saldırgan flaş kredi aracılığıyla WBNB ödünç aldı.

  • Adım 2: Saldırgan WBNB'yi SAS'a takas etti.

  • Adım 3: Saldırgan bir kontrat konuşlandırdı ve saldırı mantığını constructor() içinde çalıştırdı. Bu, protokolün is_contract() kontrolünü atlatmak için kullanıldı; zira token kontratı, transfer() göndericisinin beyaz listedeki bir adres veya EOA olmasını zorunlu kılıyordu.

  • Adım 4: Saldırgan SAS'ı havuza aktardı; bu satış yolunu tetikledi ve sellBurn'ü biriktirdi.
  • Adım 5: Saldırgan ikinci bir kontrat konuşlandırdı ve yine constructor() içinde sıradan bir transfer başlattı. 4. Adımdan itibaren sellBurn sıfır olmadığından bu transfer _burnFromPair() fonksiyonunu tetikledi; bu fonksiyon LP havuzundan doğrudan SAS yaktı ve ardından sync() fonksiyonunu çağırarak SAS rezervini 1 wei'ye indirdi.
  • Adım 6: Saldırgan ters takas gerçekleştirerek kalan SAS'ı kâr için sattı.

Sonuç

Bu olayın temel nedeni, SAS tokeninin özel transfer mantığındaki bir açıktır: sıradan bir transfer, SAS'ı doğrudan LP havuzundan yakabilir ve rezervlerini azaltılmış bakiyeyle senkronize edebilirdi; bu sayede birikimli satış faaliyeti havuzun SAS rezervinin keyfi biçimde azaltılmasına ve buradan da normal bir takas yoluyla hasat edilebilecek büyük bir fiyat bozulmasına dönüştürülebildi.

Tokenler, harici bir AMM havuzuna erişip normal takas yolları dışında rezervlerini mutasyona uğratmamalıdır. Deflationary bir tasarım gerçekten bir havuzdan yakmayı gerektiriyorsa, yakma ve buna eşlik eden sync() güvenilir bir bekçi veya hız sınırlı bir zamanlama gibi sıkı kontrollü bir iç tetikleyiciye bağlı olmalı; keyfi kullanıcı transferlerinin üzerine eklenmemelidir.


8. Bilinmeyen-EIP-7702 Olayı

Kısa Özet

3 Nisan 2026'da EIP-7702 aracılığıyla yetkilendirilmiş kod etkinleştiren BNB Chain üzerindeki bir kullanıcı hesabı yaklaşık $17,2K değerinde varlık kaybetti. Yetkilendirilmiş kod, uygun erişim kontrolü olmaksızın bir pancakeV3SwapCallback() fonksiyonunu açığa çıkardı. Saldırgan bu callback'i hazırlanmış calldata ile doğrudan çağırarak kurban hesabını tokenlerini saldırganın kontrolündeki bir adrese transfer etmeye zorladı.

Arka Plan

Kurban EOA, hesabın takas ile ilgili mantığı çalıştırabilmesi için EIP-7702 Tip-4 işlemi kullanarak yetkilendirilmiş kod atadı. Ancak yetkilendirilmiş uygulama, yalnızca meşru bir PancakeSwap V3 havuz callback'i sırasında çağrılması amaçlanan herkese açık bir pancakeV3SwapCallback() fonksiyonu içeriyordu.

Güvenlik Açığı Analizi

Temel neden, yetkilendirilmiş kontratın (0x02C809...aEDbAE) pancakeV3SwapCallback() fonksiyonundaki eksik erişim kontrolüdür.

Doğru bir UniswapV3/PancakeV3 callback tasarımında, callback msg.sender'ın beklenen kanonik havuz olduğunu doğrulamalıdır (fabrika + token çifti + ücret sınıfından türetilmiş veya güvenilir bir havuz listesiyle doğrulanmış). Bu durumda söz konusu doğrulama eksikti; dolayısıyla herhangi bir harici arayan callback'i doğrudan çağırabiliyordu.

Callback, onu barındıran hesaptan token transferlerini çalıştırdığından, eksik msg.sender kontrolü, pozitif amount0Delta/amount1Delta içeren herhangi bir harici çağrının callback içindeki ödeme yoluna girmesi ve herhangi bir gerçek takas gerçekleşmeksizin kurban hesabından token çıkarması anlamına gelir.

Saldırı Analizi

Aşağıdaki analiz, 0x5b2c...4261 işlemine dayanmaktadır.

  • Adım 1: Saldırgan, kurbanın tokenlerini saldırganın kontrolündeki adreslere taşımak için callback transfer mantığını tetikleyen hazırlanmış parametrelerle doğrudan pancakeV3SwapCallback() fonksiyonunu çağırdı.

Sonuç

Bu olay, katı callback kimlik doğrulaması olmaksızın bir EIP-7702 hesabına takas-callback mantığı konuşlandırılmasından kaynaklandı. pancakeV3SwapCallback() fonksiyonu erişim kontrolünden yoksun olduğundan, callback herhangi bir harici arayan tarafından tetiklenebilir ve meşru bir takas hiç gerçekleşmeksizin kurban hesabından token çıkarmak için kullanılabiliyordu.

V3 tarzı callback'leri uygulayan herhangi bir kontrat veya yetkilendirilmiş EIP-7702 kodu için geliştiriciler, callback herhangi bir transfer mantığına girmeden önce msg.sender'ın kanonik PancakeV3 havuzu olduğunu (güvenilir fabrika, token çifti ve ücret sınıfından türetilmiş) doğrulamalıdır.


9. Silo Finance Olayı

Kısa Özet

3 Nisan 2026'da Arbitrum üzerindeki Silo Finance soUSDC kasası yaklaşık $359K'lık bir saldırıya maruz kaldı. Temel neden üç açığın bir araya gelmesiydi: piyasa fiyatı yaklaşık 0,12'ye çökmesine rağmen tokeni hâlâ ~1,133 olarak fiyatlayan değişmez bir wstUSR oracle'ı, yalnızca kasanın kendi yatırımlarını kısıtlayan ancak harici yatırımları kısıtlamayan soUSDC üzerindeki arz sınırı mekanizması ve karşılık gelen soUSDC payları basmaksızın harici olarak alacaklandırılan bUSDC paylarını sayan bir totalAssets() muhasebe açığı. Saldırgan, sıfır sınırlı wstUSR piyasasına receiver=soUSDC olarak doğrudan USDC yatırarak kasanın pay fiyatını şişirdi, aşırı değerlendirilmiş wstUSR teminatına karşı aynı USDC'yi geri ödünç aldı ve daha önce elde edilen soUSDC paylarını şişirilmiş değerleme üzerinden itfa etti; açık, çekim kuyruğundaki diğer sağlıklı piyasalardan çekildi.

Arka Plan

Silo Finance, Arbitrum üzerinde riskten izole bir borç verme protokolüdür. Her Silo piyasası iki taraflı bir borç verme çiftidir (örn. wstUSR/USDC): borçlular teminat (wstUSR) yatırır ve borç verme varlığını (USDC) ödünç alır; borç verenler USDC yatırır ve faiz kazanır. Bir borç veren USDC'yi belirli bir piyasaya yatırdığında o piyasanın yatırım payı tokenini alır. Bir borçlu teminat yatırdığında teminat payı tokeni (örn. bwstUSR-149) alır.

soUSDC, USDC borç vermeyi bir araya getirmek için birden fazla Silo piyasasının üzerinde oturan bir SiloVault'tur. Kullanıcılar soUSDC'ye USDC yatırır ve soUSDC payı alır. Kasa ardından yatırılan USDC'yi ayırıcı tarafından belirlenen arz sınırlarına göre onaylanmış Silo piyasalarına yönlendirir; kasanın kendisi yatırdığı her piyasanın bUSDC paylarını tutar. Bir kullanıcı soUSDC paylarını itfa ettiğinde kasa, totalAssets() kullanarak payların ne kadar USDC değerinde olduğunu hesaplar; bu fonksiyon çekim kuyruğundaki her piyasayı dolaşır ve kasanın her birindeki bUSDC pay bakiyesini toplar. Kasa ardından itfa sahibine ödeme yapmak için temel piyasalarından USDC çeker.

wstUSR (Sarılmış Stake Edilmiş USR), Resolv tarafından ihraç edilen USR stabilcoininin bir staking türevidir. Resolv'un saldırıya uğramasının ardından USR pegged değerini yitirdi, stUSR de peg'ini kaybetti ve wstUSR'nin ikincil piyasa fiyatı yaklaşık 0,12'ye çöktü. Ancak wstUSR için Chainlink beslemesi yalnızca wstUSR/stUSR döviz kurunu (~1,133) takip ediyordu ve protokol 1 stUSR = 1 USD varsayımını örtük olarak benimsediğinden oracle, wstUSR'yi piyasa gerçekliğiyle ~10 kat fark oluşturarak ~1,133 olarak fiyatlamaya devam etti.

Güvenlik Açığı Analizi

wstUSR/USDC piyasasının oracle adresi SiloConfig'de değişmez olarak sabit kodlanmıştır ve değiştirilemez. Oracle kontratının (0x836a1a...04425e) kendisi, temel Chainlink beslemesi (açıklama: "wstUSR / stUSR Döviz Kuru") yalnızca wstUSR ile stUSR sarma oranını (~1,133) takip eden, ikincil piyasa fiyatını değil, bir ChainlinkV3Oracle'dır. Protokol 1 stUSR = 1 USD varsayımını örtük olarak benimsediğinden wstUSR'yi ~1,133 olarak fiyatlar. USR pegged değerini yitirdikten sonra stUSR de peg'ini kaybetti ve wstUSR açık piyasada ~0,12'ye çöktü; ancak oracle ~1,133 bildirmeye devam etti; bu ~10 katlık bir aşırı değerlemedir.

Protokol riski kısmen farkındaydı: soUSDC'nin wstUSR piyasası için arz sınırı 0 olarak belirlenmişti; yani kasa hiçbir zaman gönüllü olarak oraya USDC yönlendirmeyecekti. Ancak bu sınır yalnızca kasanın kendi giden deposit() çağrılarını yönetir. wstUSR_Market.deposit() keyfi bir receiver parametresi kabul ettiğinden, herkes USDC'yi doğrudan wstUSR piyasasına yatırıp ortaya çıkan bUSDC paylarını soUSDC'nin adresine alacaklandırabilir; arz sınırını tamamen atlayabilir.

Bu, temel istismar yolunu oluşturur. Bu tür harici bir yatırım yoluyla bUSDC payları soUSDC'nin bakiyesine girdiğinde totalAssets() bunları sayar: çekim kuyruğundaki her piyasayı dolaşır ve kasanın gerçek pay bakiyesini okur; pozisyonun gönüllü olarak girilip girilmediğini kontrol etmez. Bu arada kasanın kendi mint mantığı hiçbir zaman çağrılmadığından bu harici olarak alacaklandırılan pozisyonlar için yeni soUSDC payı basılmaz. Sonuç olarak totalShares aynı kalırken totalAssets artar ve soUSDC pay fiyatı şişer.

Saldırı Analizi

Aşağıdaki analiz, 0xf77a...f3e1 işlemine dayanmaktadır.

Saldırgan önce ikincil piyasada token başına ~0,12 fiyatla wstUSR satın aldı.

  • Adım 1: Morpho'dan yaklaşık 4.236.352 USDC flaş kredi aldı. Oracle fiyat uyuşmazlığı tek başına yeterli değildir; wstUSR piyasasında sıfır USDC likiditesi vardı (sınır=0, soUSDC oraya hiçbir zaman yatırım yapmamıştı); dolayısıyla aşırı değerlendirilmiş teminata karşı ödünç alınacak bir şey yoktu. Flaş kredi, sonraki yatırım ve bağış adımları için gereken sermayeyi sağlar.

  • Adım 2: wstUSR'yi wstUSR piyasasına teminat olarak yatırdı ve bwstUSR-149 aldı. Bu, 5. Adımın borçlanmasına hazırlıktır; oracle 13.797 wstUSR'yi ~15.633 değerinde fiyatlar (her biri 1,133'ten), saldırgan ise yalnızca ~1.656 ödedi.

  • Adım 3: ~4.222.007 USDC'yi soUSDC kasasına yatırdı ve soUSDC payları aldı (toplam arzın ~%91,5'i). Kasa bu USDC'yi mevcut sağlıklı piyasalara yönlendirir (wstUSR piyasasına değil, çünkü sınır=0). Bu soUSDC payları, 6. Adımda kâr elde etmek için kullanılacak araçtır; saldırganın ne kadar fazla payı olursa pay fiyatı şişirildiğinde o kadar çok yararlanır.
  • Adım 4: wstUSR_Market.deposit(receiver=soUSDC) aracılığıyla ~14.344 USDC'yi doğrudan wstUSR piyasasına yatırdı ve soUSDC'ye bUSDC-149 basti. Ortaya çıkan bUSDC payları saldırganın adresine değil soUSDC'nin adresine alacaklandırıldı. Bu, temel manipülasyondur: soUSDC'nin totalAssets() artık bu bUSDC paylarını nominal değerinde (~14.344 USDC) içerir; ancak kasanın kendi yatırım mantığı hiçbir zaman çağrılmadığından yeni soUSDC payı basılmaz; totalAssets artar, totalShares aynı kalır ve soUSDC pay fiyatı şişer. Aynı zamanda bu, daha önce boş olan wstUSR piyasasında USDC likiditesi oluşturur; bir sonraki adım için gereklidir.
  • Adım 5: 2. Adımda yatırılan teminatı kullanarak wstUSR piyasasından ~14.344 USDC ödünç aldı. Oracle teminatı ~15.633 olarak fiyatlar; dolayısıyla %92 maxLTV'de saldırgan ~14.344 ödünç alabilir. Bu, 4. Adımda bağışlanan USDC'yi geri kazanır; borçlanma ve bağış nakit olarak nötrdür. Ancak wstUSR piyasası artık tamamen tükenmiştir: tüm USDC ödünç alınmıştır; geriye yalnızca neredeyse değersiz wstUSR teminatıyla desteklenen bekleyen bir kredi kalmıştır. soUSDC, bUSDC paylarını totalAssets() içinde nominal değerinde tutmaya devam eder.
  • Adım 6: 3. Adımda elde edilen tüm soUSDC paylarını itfa etti. Pay fiyatı, 4. Adımın bağışından şişirildiğinden saldırgan ~4.235.143 USDC aldı; 3. Adımda yatırılan 4.222.007'den ~13.136 fazla. Kasa, wstUSR piyasasından çekmeye çalışır ancak sıfır likidite bulur (5. Adımda ödünç alındı); bu nedenle açığı çekim kuyruğundaki diğer sağlıklı piyasalardan tamamlar. Kayıp burada gerçekleşir: diğer soUSDC yatırımcılarının piyasalarından gerçek USDC şişirilmiş itfayı karşılamak için aktarılır.
  • Adım 7: Flaş krediyi geri ödedi.

32 döngünün ardından soUSDC, wstUSR piyasasında nominal değeri ~359K olan ancak bunun çok küçük bir kısmı değerinde wstUSR teminatıyla desteklenen bUSDC pozisyonlarını elinde tutmaktadır; %100 kullanım oranı, kalan soUSDC yatırımcılarının üstleneceği fiilen geri kazanılamaz takipteki alacaklardır.

Sonuç

Bu olay, depegged bir varlığın piyasa fiyatı yerine staking döviz kurunu takip eden bir oracle'ın, karşılık gelen payları basmaksızın harici olarak alacaklandırılan pozisyonları totalAssets() içinde sayan bir kasa muhasebe sisteminin ve yalnızca kasanın kendi yatırımlarını kısıtlayan ancak harici yatırımları kısıtlamayan bir arz sınırı mekanizmasının bir araya gelmesiyle gerçekleşti. Oracle adresinin SiloConfig'de değişmez olması, sorun ortaya çıktıktan sonra herhangi bir acil düzeltmeyi engelledi.

Birden fazla borç verme piyasasını bir araya toplayan kasa protokolleri, totalAssets() fonksiyonunun yalnızca kasanın kendi yatırım operasyonları aracılığıyla girdiği pozisyonları hesaba katmasını, harici olarak alacaklandırılan pay bakiyelerini değil, sağlamalıdır. Oracle adresleri kalıcı olarak değişmez olmamalıdır; temel varlıklar pegged değerini yitirdiğinde fiyat beslemesi güncellemeleri için acil durum yönetişim mekanizmaları mevcut olmalıdır.


Get Started with Phalcon Security

Detect every threat, alert what matters, and block attacks.

Try now for free

BlockSec Hakkında

BlockSec, tam kapsamlı bir blok zinciri güvenliği ve kripto uyumluluk sağlayıcısıdır. Müşterilerin kod denetimi (akıllı kontratlar, blok zinciri ve cüzdanlar dahil) gerçekleştirmesine, saldırıları gerçek zamanlı olarak engellenmesine, olayları analiz etmesine, yasadışı fonları takip etmesine ve protokol ile platformların tam yaşam döngüsü boyunca AML/CFT yükümlülüklerini karşılamasına yardımcı olan ürün ve hizmetler geliştirmekteyiz.

BlockSec, saygın konferanslarda birden fazla blok zinciri güvenliği makalesi yayımlamış, çeşitli DeFi uygulamalarının sıfır gün saldırılarını raporlamış, 20 milyon dolardan fazlayı kurtarmak için birden fazla hacklemeyi engellemiş ve milyarlarca dolarlık kripto para güvence altına almıştır.

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit