Geçtiğimiz hafta (2026/08/17 - 2026/08/23) boyunca, toplamda yaklaşık 10,26 milyon dolarlık zarara neden olan aşağıdaki 2 önemli güvenlik olayı öne çıkıyor.
| Tarih | Olay | Tür | Tahmini Kayıp |
|---|---|---|---|
| 2026/08/18 | MAYAChain | İş Mantığı Kusuru | ~$1.76M |
| 2026/08/23 | Term Finance | Hatalı Yönetişim Tasarımı | ~$8.5M |
Seçim nedenleri
- MAYAChain: Zincirleme bir muhasebe ve durum doğrulama hatasının, tek bir kötü niyetle hazırlanmış bir depozitonun giden mutabakat sürecini bozmasına ve gerçek bir destek olmadan düşük likiditeli bir havuzun kayıtlı bakiyesini şişirmesine yol açması nedeniyle seçildi; bu durum, her biri kendi başına sınırlı olan birkaç düşük seviyeli kusurun, çapraz zincir likidite ağından değer çekmek üzere nasıl birleşebildiğini göstermektedir.
- Term Finance: Sıfıra yakın yönetişim katılımının, kötü niyetli bir teklifi reddedecek bir seçmen kitlesi bırakmaması ve infaz gecikmesinin arkasında herhangi bir bekçi (guardian) veya iptal yolunun bulunmaması nedeniyle seçildi; bu durum, minimum sermayeye sahip bir saldırganın oyları domine etmesine, bir teklifi geçirmesine ve altı protokol kasasından yaklaşık 8,5 milyon dolar çekmesine olanak sağladı.
Web3 için En İyi Güvenlik Denetçisi
Lansmandan önce tasarımı, kodu ve iş mantığını doğrulayın
Haftanın Öne Çıkanı: Term Finance
Term Finance bu hafta öne çıkıyor çünkü meydana gelen hata bir kodlama hatası değil, protokollerin her kasa ile birlikte ayrı bir zincir üstü DAO sunmasıyla büyüyen bir risk sınıfı olan bir yönetişim tasarım kusuruydu: neredeyse hiç kimse katılmadığında, oy kontrolü ucuza satın alınabilir ve kasanın kendi yönetişimi saldırı yüzeyi haline gelir.
23 Ağustos 2026'da, Ethereum üzerinde sabit oranlı bir borç verme protokolü olan Term Finance, bir saldırganın kasalarının zincir üstü yönetişimini ele geçirmesiyle yaklaşık 8,5 milyon dolar kaybetti. Neredeyse hiçbir mevduat sahibi bir kasanın yönetişim tokenini hiçbir zaman basmamış olduğundan, saldırgan kasanın oy gücünün büyük bir çoğunluğunu kabaca 0,5 ETH karşılığında elde edebildi, protokolün destek eşiği ve minimum katılım kontrollerini geçebildi ve kasanın stratejilerini iptal eden ve varlıklarını aktaran kötü niyetli bir teklifi yürürlüğe koydu; Term'in altı kasası bu şekilde boşaltıldı [1].
Arka Plan
Term Finance, Ethereum üzerinde sabit oranlı bir borç verme protokolüdür. Term Vaults, bunun üzerine katmanlanmış ayrı bir üründür: her kasa, Yearn V3 kodu üzerine inşa edilmiş bir ERC-4626 kasasıdır; burada bir meta kasa tek bir varlığı kabul eder ve onu bir dizi strateji kasası arasında dağıtır. Term'in çerçevesi, her kasayla birlikte bir Aragon OSx DAO'su ve bir TokenVoting sözleşmesi dağıtır ve bu DAO, birlikte gönderildiği kasa üzerinde yükseltme ve rol yetkisine sahiptir. Bu nedenle bir kasa, kim tarafından düzenlendiğinden veya içine hiç sermaye tahsis edilip edilmediğinden bağımsız olarak, doğuşundan itibaren kendi yönetişim yüzeyini taşır.
Yönetişim kararları TokenVoting tarafından alınır. Her kasanın kendi pay tokeni ve buna karşılık gelen bir Aragon GovernanceWrappedERC20 yönetişim sarmalayıcısı vardır; analiz edilen ETH Meta Vault'ta bunlar tmvETH ve gtmvETH'tir. Herhangi bir pay tokeni sahibi, yönetişim tokenini bire bir almak için depositFor()'u çağırabilir ve herhangi bir yönetişim tokeni sahibi, elde edilen oyları delegate() edebilir. Bir teklif oluşturulduğunda, TokenVoting.createProposal() bir snapshotBlock, bir supportThreshold ve bu anlık görüntüdeki token arzından türetilen bir minVotingPower kaydeder; oy gücü ardından o bloktaki sarmalayıcıdan okunur.
Zafiyet Analizi
Bu olayın merkezindeki yönetişim sözleşmesi TokenVoting'dır. Teklif infazı yalnızca _canExecute() ile kısıtlanır; bu fonksiyon, normal (erken olmayan) bir teklif için, oylamanın henüz infaz edilmemiş olmasını, teklifin kapalı olmasını ve iki kontrolün geçmesini gerektirir: isSupportThresholdReached() ve isMinParticipationReached().

Her iki kontrol de çoğunluk oylamasının doğru bir uygulamasıdır, ancak her biri mutlak bir miktar yerine nispi bir oranı ölçmektedir. isSupportThresholdReached() yalnızca evet oylarının, belirlenen orana göre hayır oylarını geride bırakmasını gerektirir:

isMinParticipationReached(), verilen oyların, anlık görüntüde minParticipation * totalSupply olarak türetilen minVotingPower'a ulaşmasını gerektirir:

Temel neden, bu yönetişim tasarımının bir teklifi ilerletmek için gereken sermaye veya katılım genişliği üzerinde mutlak bir alt sınır belirlememiş olmasıdır. Her iki kapı da yalnızca verilen oylara ve token arzına göre nispidir ve neredeyse hiçbir tmvETH sahibi gtmvETH'e sarmalayarak yönetişime katılmadığından, bu arz ve onunla birlikte minimum katılım eşiği sıfıra yakın kaldı. Bu nedenle, her iki kontrolü de geçmek için neredeyse boş bir seçmen kitlesinin nispi bir çoğunluğu yeterliydi ve bu kadar az seçmenle, teklifi reddedebilecek karşı oyları verecek kimse yoktu. Minimum oylama süresi infazı geciktirdi, ancak bekçi veya iptal yolu olmadığından, bu gecikme geçen teklifi önlemek yerine yalnızca ertelemiş oldu.
Saldırı Analizi
Saldırgan bir kasanın yönetişim tokeninin kontrol edici bir payını elde etti, ardından bunu o kasayı boşaltan bir teklifi geçirmek ve yürütmek için kullandı; aynı teknik Term'in altı kasasında da uygulandı. Aşağıdaki analiz, 0xd354a1...d3014129 ve 0x9f273f...44c2e8a0 işlemlerine dayanarak bir kasayı izlemektedir.
-
Adım 1: Saldırgan,
0,5 ETH'yi bir Mayan Finance yönlendiricisi (forwarder) üzerinden0,485 tmvETH'e takas etti; bu yönlendirici takası yönlendirdi ve kasa paylarını saldırgana ulaştırdı. -
Adım 2: Saldırgan,
0,485 tmvETH'yi bire bir olarak0,485 gtmvETH'e sarmalayarak, sonraki adımlarda kullanılan oy gücünü elde etti. -
Adım 3: Saldırgan
propose()'u çağırdı; bu, kendi oy gücünü okudu veTokenVoting.createProposal()'ı çağırdı. Sözleşme anlık görüntüyü kaydetti ve o bloktaki toplam yönetişim arzını yalnızca0,535 gtmvETHolarak okudu; böylece saldırganın payı tüm seçmen kitlesinin yaklaşık %90,66'sını oluşturdu. -
Adım 4: Saldırgan, teklifin yararına tüm oy gücünü vermek için
vote()'u çağırdı ve tek katılımcı haline geldi. -
Adım 5: Oylama süresi sonunda, saldırgan
executeProposal()'ı çağırdı.canExecute()kapısıisSupportThresholdReached()'i kontrol etti: saldırgan tek "evet" oyu veren kişi olduğundan, destek oranı %50 eşiğini büyük ölçüde aştı. ArdındanisMinParticipationReached()'i kontrol etti: saldırganın kendi oy gücü tek başınaminVotingPower'ı aştı. Her iki kontrol de geçti. -
Adım 6: Kötü niyetli teklif ardından yürütüldü;
tmvETHkasasının stratejisine tahsis ettiği fonları geri çekti, bunları kasanın elinde tutulan likitWETH'e çevirdi ve saldırganın varlıkları çekmesine izin verdi. Term'in altı kasası genelinde uygulanan saldırı, toplam yaklaşık 8,5 milyon dolarlık zarara neden oldu.
Sonuç
Bu olay, bir kodlama hatasından ziyade hatalı bir yönetişim tasarımından kaynaklandı: destek ve katılım kontrolleri tamamen nispiydi, dolayısıyla neredeyse boş bir seçmen kitlesiyle, ucuza elde edilen bir çoğunluk hiçbir karşı oyla karşılaşmadı ve infaz gecikmesinin arkasında herhangi bir bekçi veya iptal yolu yoktu. Varlıkların gözetimini kontrol eden yönetişim, mutlak bir yeter sayı (quorum) veya katılım alt sınırını uygulamalı ve herhangi bir infaz gecikmesini bir bekçi veya iptal yolu ile izlenen bir teklif akışıyla desteklemelidir, çünkü bir zaman kilidi (timelock), birisi bu süre içinde harekete geçemediği takdirde geçen bir teklifi yalnızca erteler.
Bu Haftaki Diğer Olaylar
MAYAChain
18 Ağustos 2026'da, bir Cosmos-SDK çapraz zincir likidite ağı olan MAYAChain, tek bir kötü niyetle hazırlanmış depozitonun zincirin dahili muhasebesini bozması sonucu yaklaşık 1,76 milyon dolar kaybetti. Geçerli para çekme işlemlerinin başarısız olmuş gibi görünmesini sağlayarak, bu depozito, düşük likiditeli bir havuzun kayıtlı yerel token bakiyesini gerçek bir destek olmadan şişiren bir kurtarma yolunu tetikledi; saldırgan ardından likidite ekleyip çekerek bu şişirilmiş değeri boşalttı [2]. Doğrulanmış zincir üstü çıkışlar yaklaşık 1,36 milyon dolardı, esas olarak 20,83 BTC; kalan yerel token bakiyeleriyle birlikte resmi tahmin yaklaşık 1,76 milyon dolara ulaşıyor.
Arka Plan
MAYAChain, yerel varlığı CACAO olan bir Cosmos-SDK çapraz zincir likidite ağıdır. Harici zincirlerdeki olaylar doğrulayıcılar (validators) tarafından gözlemlenir ve gözlemlenen işlemler olarak MAYAChain'e yeniden yayınlanır. Gelen bir eylemin varlıkları dışarı göndermesi gerektiğinde, düğüm bir veya daha fazla TxOutItem zamanlar ve daha sonra gözlemlenen giden işlemleri bu zamanlanmış kayıtlarla mutabakat eder. Tüm havuz varlıkları paylaşılan Asgard kasalarında birlikte gözetim altında tutulur; her likidite havuzu, ayrılmış bir bakiye yerine bu paylaşılan gözetim üzerinde bir muhasebe pozisyonudur ve para çekme işlemleri Asgard'dan bir havuzun kayıtlı bakiyelerine göre ödenir.
Ticaret hesapları, ARB~ETH ve ARB~LINK gibi ticaret varlıkları için yerel MAYAChain muhasebe pozisyonlarıdır. Bir ticaret hesabından para çekme işlemi, trade-:ARB~LINK gibi bir not (memo) içeren yerel bir MsgDeposit üzerinden başlatılır. Kullanıcı tek bir yerel işlemi imzalamasına rağmen, depozito işleyicisi dahili bir gözlemlenen işlem yeniden oluşturur ve yerel işlem hash'i ile anahtarlanmış bir ObservedTxVoter saklar.
Zafiyet Analizi
Temel neden tek bir izole hata değildi; bir araya gelen bir muhasebe ve durum doğrulama kusurları zinciriydi. Hatalı mantık, MAYANode'un depozito ve giden işlem işleyicilerinde bulunmaktadır.
Birincisi, handler_deposit.go'da, yerel bir işlemdeki her mesaj, işlem hash'i ile anahtarlanmış yeni bir ObservedTxVoter oluşturur ve bunu SetObservedTxInVoter() ile kaydeder:
txIn := ObservedTx{Tx: tx}
txInVoter := NewObservedTxVoter(txIn.Tx.ID, []ObservedTx{txIn})
txInVoter.Height = ctx.BlockHeight()
txInVoter.FinalisedHeight = ctx.BlockHeight()
txInVoter.Tx = txIn
h.mgr.Keeper().SetObservedTxInVoter(ctx, txInVoter)
Bir toplu işlemdeki her mesaj aynı tx.ID'yi paylaştığından, sonraki bir mesaj, önceki mesajlar tarafından yazılan seçmen durumunun üzerine yazar ve bunların giden işlem zamanlama meta verilerini yok eder.
İkincisi, handler_common_outbound.go'da, giden işlem mutabakatı voter.OutboundHeight'tan (veya bu değer sıfır olduğunda voter.FinalisedHeight'tan) başlar ve imzalama periyoduna göre ileriye doğru taranır:
outHeight := voter.OutboundHeight
if outHeight == 0 {
outHeight = voter.FinalisedHeight
}
for height := outHeight; height <= ctx.BlockHeight(); height += signingTransPeriod {
txOut, err = h.mgr.Keeper().GetTxOut(ctx, height)
...
}
Seçmen bu şekilde üzerine yazıldığında, tarama sonlandırılmış depozito yüksekliğinde başlar ve zamanlanmış giden işlemleri tutan bloğu hiçbir zaman incelemez, dolayısıyla işleyici bunları eksik olarak değerlendirir ve ceza-kurtarma (slash-recovery) yolunu tetikler.
Üçüncüsü, helpers.go'da, kurtarma yolu, ham gözlemlenen miktarı kullanarak "eksik" varlığı bir CACAO sübvansiyonu olarak değerlendirir, havuzun gerçek varlık derinliğine karşı hiçbir üst sınır uygulanmaz:
f.stolenAsset = f.stolenAsset.Add(coin.Amount)
runeValue := pool.AssetValueInRune(coin.Amount)
f.subsidiseRune = f.subsidiseRune.Add(runeValue)
Yalnızca yaklaşık 0,11 LINK varlık tarafı derinliğine sahip bir havuzda, bu üst sınır uygulanmayan dönüştürme, gözlemlenen bir LINK miktarını devasa bir CACAO değerine eşleyebilirdi. Aynı yordam ardından, şişirilmiş havuz bakiyesini fonlama transferini denemeden önce duruma işlemler:
pool.BalanceCacao = pool.BalanceCacao.Add(f.subsidiseRune)
pool.BalanceAsset = common.SafeSub(pool.BalanceAsset, f.stolenAsset)
if err = mgr.Keeper().SetPool(ctx, pool); err != nil {
...
}
runeToAsgard := common.NewCoin(common.BaseAsset(), f.subsidiseRune)
if err = mgr.Keeper().SendFromModuleToModule(ctx, ReserveName, AsgardName, common.NewCoins(runeToAsgard)); err != nil {
ctx.Logger().Error("fail to send subsidy from bond to asgard", "error", err)
return err
}
Havuz yazma işlemi transferden önce işlendiğinden, transfer fonlanamazsa havuzun BalanceCacao'su hiçbir zaman geri alınmaz. Son olarak, handler_observed_txout.go'da, çağıran taraf döndürülen hatayı yutar, seçmeni tamamlandı olarak işaretler ve devam eder, böylece tutarsız bir havuz durumu kalıcı olabilir:
_, err = handler(ctx, m)
if err != nil {
ctx.Logger().Error("handler failed:", "error", err)
slashObservedOutbound("failed_outbound")
voter.SetDone()
h.mgr.Keeper().SetObservedTxOutVoter(ctx, voter)
continue
}
Saldırı Analizi
Saldırgan bu kusurları tek bir yerel işlemde birleştirdi, ardından şişirilmiş havuzdan değer çıkardı. Aşağıdaki analiz MAYAChain işlemine 516BA14D...E9B7 dayanmaktadır.
-
Adım 1: Saldırgan, 23 mesaj içeren
516BA14D...E9B7yerel işlemini gönderdi: 20trade-:ARB~ETHpara çekme işlemi, 2trade-:ARB~LINKpara çekme işlemi ve son olarak bir baz birim değerindeDONATE:ARB.LINK. -
Adım 2: Ticaret para çekme işlemleri geçerli zamanlanmış giden işlemler oluşturdu, ancak son
DONATEmesajı, aynı yerel işlem hash'i için paylaşılan gelen seçmenin üzerine yazdı ve önceki para çekme işlemlerinin giden işlem zamanlamasını sildi. -
Adım 3:
ARB.LINKgiden işlemleri daha sonra gözlemlendiğinde, mutabakat taraması, bozulmuş seçmenin yükseklik alanlarını kullandı ve zamanlanmış giden işlemleri tutan bloğa hiçbir zaman ulaşmadı, dolayısıyla bunları eksik olarak değerlendirdi. -
Adım 4: Ceza-kurtarma yolu, eksik LINK'i ince
ARB.LINKhavuzuna karşı değerlendirdi ve havuzunCACAOtarafını yaklaşık49,45M CACAOkadar şişirdi. Sübvansiyonu fonlaması gereken Reserve-to-Asgard transferi başarısız oldu, çünkü Reserve yalnızca yaklaşık168K CACAOtutuyordu, şişirilmiş sübvansiyonun çok altında; ancak değiştirilmiş havuz bakiyesi kalıcı hale geldi ve başarısız işleyici tamamlandı olarak işaretlendi. -
Adım 5: Daha sonraki bir yükseklikte, saldırgan bozulmuş havuza
100 CACAOve az miktarda LINK ile likidite ekledi. Havuzun bir tarafı orantısız bir şekilde çok fazla itildiğinden, likidite ekleme formülü saldırgana mevcut yaklaşık731Mbirime karşı yaklaşık1TLP birimi verdi. -
Adım 6: Saldırgan pozisyonunun neredeyse tamamını hemen geri çekti, şişirilmiş havuz bakiyesine karşı paylaşılan Asgard kasalarından ödenen yaklaşık
48,87M CACAOve98,82 LINKaldı ve çıkarılanCACAO'yu MAYAChain havuzları aracılığıyla BTC ve diğer varlıklara takas etti.CACAOfiyatı, satış baskısı sırasında yaklaşık$0.115'ten$0.013'e yakın bir düşük seviyeye düştü.
Saldırganın çektiği 48,87M CACAO, saldırı öncesi fiyata göre nominal olarak 5 milyon doların üzerinde bir değere sahipti, ancak bunun tamamı harici gelir olarak gerçekleşmedi: büyük bir kısmı havuzlara geri takas edildi, CACAO fiyatını çökertti ve saldırganla ilgisi olmayan fırsatçı arbitrajcılar da çöküş sırasında değer çıkardı. Doğrudan doğrulanan zincir üstü çıkarım yaklaşık 1,36 milyon dolardı, esas olarak 20,83 BTC; saldırganın kalan CACAO ve ticaret hesabı bakiyelerini sayarak bu rakam resmi tahmin olan yaklaşık 1,76 milyon dolara çıkmaktadır.
Sonuç
Bu olay, tek bir hatadan ziyade bir muhasebe ve durum doğrulama kusurları zincirinden kaynaklandı: hiçbir adım tek başına yıkıcı değildi, ancak birlikte, kötü niyetle hazırlanmış bir depozitonun ince bir havuzun kayıtlı bakiyesini desteksiz bir değere dönüştürmesine olanak sağladılar. Temel gereklilik atomiklik ve sınırlı güvendir: bir muhasebe değişimi ve bunu fonlamak amacıyla yapılan transfer birlikte başarılı olmalı veya birlikte başarısız olmalıdır, başarısız bir kurtarma yolu asla tamamlandı olarak işaretlenmemelidir ve düşük likiditeli havuzlara karşı yapılan değerlendirmelerin bir üst sınırı olmalıdır. Paylaşılan gelen durum da, aynı işlemdeki sonraki bir mesaj tarafından sessizce üzerine yazılmamalıdır.
Phalcon Explorer ile Başlayın
Akıllıca Hareket Etmek İçin İşlemlerin Derinliklerine İnin
Şimdi ücretsiz deneyinKaynaklar
BlockSec Hakkında
BlockSec, tam yığın (full-stack) bir blockchain güvenliği ve kripto uyumluluk sağlayıcısıdır. Müşterilerin kod denetimi (akıllı sözleşmeler, blockchain ve cüzdanlar dahil) gerçekleştirmelerine, saldırıları gerçek zamanlı olarak durdurmalarına, olayları analiz etmelerine, yasadışı fonları izlemelerine ve AML/CFT yükümlülüklerini yerine getirmelerine yardımcı olan, protokollerin ve platformların tüm yaşam döngüsü boyunca kullanılan ürün ve hizmetler geliştiriyoruz.
BlockSec, saygın konferanslarda birden fazla blockchain güvenliği makalesi yayımlamış, DeFi uygulamalarında birçok sıfır gün (zero-day) saldırısını bildirmiş, 20 milyon dolardan fazlasını kurtarmak için birden fazla saldırıyı engellemiş ve milyarlarca dolarlık kripto para birimini güvence altına almıştır.
-
Resmi web sitesi: https://blocksec.com/
-
Resmi Twitter hesabı: https://twitter.com/BlockSecTeam



