4 Ağustos 2021'de Popsicle Finance, bir saldırıdan kaynaklanan büyük bir finansal kayıp (20 milyon dolardan fazla) yaşadı [1].
Manuel analizin ardından, bunun bir çift talep saldırısı olduğunu doğruladık; yani ödül sistemindeki bir açık, saldırganın ödülleri tekrar tekrar talep etmesine izin vermektedir.
Aşağıda, saldırı sürecini ve güvenlik açığının kök nedenini açıklamak için bir saldırı işlemi kullanacağız.
Arka Plan
Popsicle Finance, farklı zincirler (örneğin Ethereum ve BSC) için birden fazla vault destekleyen bir getiri optimizasyon platformudur.
Özellikle, bir kullanıcı önce likidite sağlamak için deposit fonksiyonunu çağırır ve Popsicle LP token'ı (kısaca PLP) alır. Bunun ardından Popsicle Finance, kullanıcı adına kâr elde etmek amacıyla likiditeyi yönetir (Uniswap gibi platformlarla etkileşime girer).
Kullanıcı, Popsicle Finance'ten likiditeyi geri almak için withdraw fonksiyonunu çağırabilir; bu işlem miktarı PLP token'larına göre hesaplar.
Teşvik ödülü likiditen kaynaklanır ve zaman geçtikçe birikir.
Kullanıcı, bu saldırının anahtarı olan ödülleri talep etmek için collectFees fonksiyonunu çağırabilir.
Güvenlik Açığı Analizi
collectFees fonksiyonunda, kullanıcı için token0Reward ve token1Reward (karşılık gelen LP token çiftinin ödülleri) hesaplanır. Tüm hesaplama mantığı basittir. Ancak fonksiyon, ödülleri buna göre güncellemek için kullanılan updateVault adlı bir değiştirici kullanır.


Kısaca, updateVault şunları yapar:
- önce havuzdan birikmiş ücreti almak için
_earnFeesfonksiyonunu çağırır; - ardından havuzdaki her pay için token0 ve token1 miktarlarını temsil eden
token0PerShareStoredvetoken1PerShareStoreddeğerlerini güncellemek için_tokenPerSharefonksiyonunu çağırır; - son olarak kullanıcı için ödülleri güncellemek amacıyla
_fee0Earnedve_fee1Earnedfonksiyonlarını çağırır (sırasıylatoken0Rewardsvetoken1Rewards).

_fee0Earned ve _fee1Earned fonksiyonları aynı mantığı paylaşır; yani aşağıdaki formülü uygular (örnek olarak token0 kullanılmıştır):
user.token0Rewards += PLP.balanceOf(account) * (fee0PerShare - user.token0PerSharePaid) / 1e18
Hesaplamanın artımlı olduğuna dikkat edin; bu, kullanıcının PLP token'ı tutmasa bile hesaplanan ödülün token0Rewards'ta saklanan değerde kalmaya devam ettiği anlamına gelir.
Bu nedenle, aşağıdaki iki gözlemi yapabiliriz:
- kullanıcının ödülleri
token0Rewardsvetoken1Rewardsiçinde saklanır ve herhangi bir PLP token'ıyla ilişkilendirilmez; collectFeesfonksiyonu yalnızcatoken0Rewardsvetoken1Rewardsdurumuna bağlıdır; bu da ödüllerin PLP token'ı tutulmadan çekilebileceği anlamına gelir.
Gerçek dünya senaryosunda bu, bir kullanıcının bankaya para yatırması ve bankanın ona bir mevduat sertifikası vermesi anlamına gelir. Ne yazık ki bu sertifika ne sahteciliğe karşı korumalıdır ne de kullanıcıyla ilişkilendirilmiştir. Böyle bir durumda, kopyaları çoğaltıp başkalarına dağıtarak bankadan kâr elde etmek mümkündür.
Saldırı Akışı
Kısaca, saldırgan saldırıyı gerçekleştirmek için aşağıdaki adımları izledi:
- üç sözleşme oluşturdu. Bunlardan biri saldırıyı başlatmak için kullanılırken, diğer ikisi ödülleri almak amacıyla
collectFeesfonksiyonunu çağırmak için kullanıldı; - Flash Loan'dan yararlandı; yani AAVE'den büyük miktarda likidite ödünç aldı;
- saldırıyı gerçekleştirmek için Yatır-Çek-ÜcretTopla döngüsünü başlattı (toplamda 8 döngü vardır ve Popsicle Finance'in birden fazla vault'undan çok miktarda likidite çekilmiştir);
- Flash Loan'ı AAVE'ye iade etti ve kârları Tornado.Cash aracılığıyla aklandı.

Özellikle, Yatır-Çek-ÜcretTopla döngüsü birkaç adımdan oluşmaktadır; bunlar çevrimiçi aracımız [2] kullanılarak kolayca etiketlenebilir ve açıkça özetlenebilir:

Kâr Analizi
Toplamda saldırgan, Popsicle Finance'ten 2,56 bin WETH, 96,2 WBTC, 160 bin DAI, 5,39 milyon USDC, 4,98 milyon USDT ve 10,5 bin UNI dahil olmak üzere 20 milyon dolar elde etti. Bu sömürünün ardından saldırgan, önce diğer tüm token'ları Uniswap ve WETH aracılığıyla ETH'ye çevirdi, ardından Tornado.Cash kullanarak para aklaması gerçekleştirdi.
Katkıda Bulunanlar
Yufeng Hu, Ziling Lin, Junjie Fei, Lei Wu, Yajin Zhou @BlockSec
(Soyadına göre alfabetik sırayla)
Medium: https://blocksecteam.medium.com/
Twitter: https://twitter.com/BlockSecTeam
İletişim: [email protected]
Referans
[1] https://twitter.com/defiprime/status/1422708265423556611



