Back to Blog

Popsicle Finance Güvenlik Olayının Analizi

Code Auditing
August 4, 2021
4 min read

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:

  1. önce havuzdan birikmiş ücreti almak için _earnFees fonksiyonunu çağırır;
  2. ardından havuzdaki her pay için token0 ve token1 miktarlarını temsil eden token0PerShareStored ve token1PerShareStored değerlerini güncellemek için _tokenPerShare fonksiyonunu çağırır;
  3. son olarak kullanıcı için ödülleri güncellemek amacıyla _fee0Earned ve _fee1Earned fonksiyonlarını çağırır (sırasıyla token0Rewards ve token1Rewards).

_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:

  1. kullanıcının ödülleri token0Rewards ve token1Rewards içinde saklanır ve herhangi bir PLP token'ıyla ilişkilendirilmez;
  2. collectFees fonksiyonu yalnızca token0Rewards ve token1Rewards durumuna 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:

  1. üç 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 collectFees fonksiyonunu çağırmak için kullanıldı;
  2. Flash Loan'dan yararlandı; yani AAVE'den büyük miktarda likidite ödünç aldı;
  3. 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);
  4. 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)

https://www.blocksecteam.com

Medium: https://blocksecteam.medium.com/

Twitter: https://twitter.com/BlockSecTeam

İletişim: [email protected]

Referans

[1] https://twitter.com/defiprime/status/1422708265423556611

[2] https://tx.blocksecteam.com/

Best Security Auditor for Web3

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

BlockSec Audit