15 maja 2024 r. firma Sonne Finance została zaatakowana w sieci Optimism, co spowodowało straty sięgające 20 mln dolarów.
Po ataku użytkownik @tonyke_bot włączył się
(https://twitter.com/tonyke_bot/status/1790547461611860182)
Po wykryciu ataku przez projekt Sonne Finance szybko zawiesił wszystkie rynki na platformie Optimism i stwierdził, że rynki na platformie Base są bezpieczne.
(https://twitter.com/SonneFinance/status/1790535383005966554)
Krótki atak
Sonne Finance to zdecentralizowany protokół pożyczkowy, który rozdziela Compound V2 na Optymizm, zapewniając osobom, instytucjom i protokołom dostęp do usług finansowych. Protokół Sonne Finance agreguje tokenowe aktywa użytkowników, tworząc pulę płynności kredytowej, zapewniając użytkownikom działalność pożyczkową przypominającą bank. Podobnie jak Compound, uczestnicy protokołu mogą zastawić swoje tokeny w puli płynności kredytowej Sonne Finance i uzyskać certyfikat soToken (taki sam jak cToken). SoToken to oprocentowany certyfikat aktywów, który będzie generował określoną kwotę dochodu w miarę postępu bloku, a także będzie otrzymywał zachęty w postaci tokena SONE. Uczestnicy mogą także pożyczać inne tokeny z puli aktywów pożyczkowych Sonne, mając w rękach soToken. Na przykład uczestnicy mogą zastawić hipotekę na określoną kwotę USDC, aby uzyskać certyfikaty soUSDC, a następnie pożyczyć WETH do dalszego obiegu. Kredyty hipoteczne w protokole Sonne Finance mogą być relacją aktywów wiele do wielu. Podczas procesu udzielania kredytu hipotecznego protokół automatycznie oblicza współczynnik zdrowia (czynnik zdrowia) adresu uczestnika, gdy współczynnik zdrowia jest niższy niż 1. hipoteka na adres Produkty będą wspierać likwidację, a likwidatorzy mogą również otrzymać określone nagrody likwidacyjne.
Zależność między liczbą tokenów bazowych zdeponowanych przez użytkowników a liczbą wyemitowanych soTokenów jest głównie powiązana ze zmienną zwaną ExchangeRate. Zmienną tę można z grubsza wykorzystać do wskazania, ile wart jest każdy token bazowy. Wzór obliczeniowy dla ExchangeRate jest następujący:
W powyższym wzorze totalCash odnosi się do liczby tokenów bazowych posiadanych przez soToken, totalBorrows odnosi się do liczby tokenów bazowych pożyczonych na danym rynku, totalReserves odnosi się do całkowitej kwoty rezerwy (w tym odsetek zapłaconych przez pożyczkobiorcę), totalSupply Odnosi się do liczby wybitych soTokenów.
Podczas realizacji użytkownicy mogą określić liczbę tokenów bazowych, które chcą wykupić, wykupAmount, aby obliczyć liczbę soTokenów, które należy zniszczyć, wykupTokens Metoda obliczania jest w przybliżeniu „redeemTokens = wykupAmount / ExchangeRat”. tutaj poradzić sobie z utratą dokładności.
Istota tego ataku polega na tym, że podczas tworzenia rynku (soToken) osoba atakująca przeprowadziła pierwszą operację rzutowania hipoteką i wybiła bardzo niewiele soTokenów z niewielką liczbą tokenów bazowych, powodując, że wartość „totalSupply” soTokena była zbyt mała. Osoba atakująca następnie wykorzystała lukę polegającą na utracie precyzji kontraktu Solidity, a następnie wysłał bazowy token bezpośrednio do kontraktu soToken (soToken nie zostanie wybity, co oznacza, że „totalSupply” pozostanie niezmieniony, a „totalCash” stanie się większy) zamiast stakowania + metody rzucania aby zdeponować token bazowy. Taka operacja powoduje, że zmienna „totalCash” w kontrakcie staje się większa, ale zmienna „totalSupply” pozostaje niezmieniona, co powoduje wzrost ExchangeRate. Ostatecznie, gdy atakujący wykorzysta token bazowy, soToken, który należy zniszczyć, jest mniejszy niż soToken wybity podczas kredytu hipotecznego. Osoba atakująca wykorzystuje zdobyty soToken do pożyczenia tokenu bazowego WETH i USDC innym soTokenom (takim jak soWETH). , więcUSDC) i ostatecznie osiąga zyski sięgające 20 mln dolarów.
Kluczowe adresy biorące udział w ataku
Transakcje przygotowania ataku:
https://optimistic.etherscan.io/tx/0x45c0ccfd3ca1b4a937feebcb0f5a166c409c9e403070808835d41da40732db96
Atakuj zyskowne transakcje:
https://optimistic.etherscan.io/tx/0x9312ae377d7ebdf3c7c3a86f80514878deb5df51aad38b6191d55db53e42b7f0
Atakuj adresy powiązane z EOA:
0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb
0xae4a7cde7c99fb98b0d5fa414aa40f0300531f43
Adres powiązany z osobą atakującą (umową):
0xa78aefd483ce3919c0ad55c8a2e5c97cbac1caf8
0x02fa2625825917e9b1f8346a465de1bbc150c5b9
podstawowy token (VELO Token V2):
0x9560e827af36c94d2ac33a39bce1fe78631088db
Umowa dotycząca podatności na zagrożenia (soVELO, podobna do cToken firmy Compound):
0xe3b81318b1b6776f0877c3770afddff97b9f5fe5
Transakcja ratowania użytkownika @tonyke_bot na X:
https://optimistic.etherscan.io/tx/0x816f9e289d8b9dee9a94086c200c0470c6456603c967f82ab559a5931fd181c2
Analiza procesu ataku
Wstępne podsumowanie
Zespół projektowy Sonne Finance przedstawił niedawno propozycję dodania rynku VELO do Sonne Finance (https://twitter.com/SonneFinance/status/1786871066075206044) i zorganizował pięć transakcji za pośrednictwem portfela z wieloma podpisami, które mają zostać zrealizowane dwa dni później ( https://optimistic.etherscan.io/tx/0x18ebeb958b50579ce76528ed812025949dfcff8c2673eb0c8bc78b12ba6377b7), te pięć transakcji służy do stworzenia rynku VELO (kontrakt soVELO) i ustalenia kilku kluczowych konfiguracji rynku, takich jak ustawienie modelu stopy procentowej, ustalenie wyroczni cenowej oraz ustalanie współczynników kredytu hipotecznego itp. Po utworzeniu rynku VELO użytkownicy mogą zdeponować tokeny VELO, aby wybić tokeny soVELO, które z kolei można wykorzystać do pożyczenia innych soTokenów.
przygotowanie ataku
Etap przygotowania ataku polega głównie na utworzeniu przez atakującego rynku VELO (kontraktu soVELO) w oparciu o informacje zawarte w propozycji projektu Sonne Finance po upływie dwudniowego okresu zablokowania propozycji, skonfigurowaniu kluczowych konfiguracji i uruchomieniu tokeny VELO do kontraktu soVELO poprzez zastawienie ich w hipotece, a także wysyła posiadane tokeny VELO bezpośrednio do kontraktu soVELO w celu zwiększenia kursu wymiany i przygotowania zysków z kolejnych ataków.
Konkretne kroki są następujące:
Po dwudniowym okresie blokady osoba atakująca najpierw spakowała operacje pierwszych czterech transakcji zawartych w propozycji w jedną transakcję (transakcja 0x45c0cc), wykorzystała ją do stworzenia rynku VELO (kontrakt soVELO) i skonfigurowała kluczowe konfiguracje . Po zainicjowaniu rynku VELO, ExchangeRate jest ustawiane na „200 000 000 000 000 000 000 000 000”.
Osoba atakująca wywołuje funkcję „mint” kontraktu soVELO w celu zdeponowania tokenów VELO i wytworzenia tokenów soVELO. Osoba atakująca określa „mintAmount” jako „400 000 001” (liczba tokenów VELO). Jak widać z funkcji „exchangeRateStoredInternal”, ponieważ „_totalSuppl” tokena soVELO wynosi w tym momencie 0, ExchangeRate jest wartością ustawioną w kroku 1. Zgodnie ze wzorem „mintTokens = currentMintAmount/changeRate” wyliczona liczba tokenów soVELO, które należy w tym momencie wybić, wynosi 2. Krótko mówiąc, na tym etapie atakujący wpłaca tokeny VELO o wartości „400 000 001” do kontraktu soVELO, a atakujący otrzymuje tokeny soVELO o wartości 2.
soVELO.mint:
Atakujący wysłał tokeny VELO o wartości „2 552 964 259 704 265 837 526” do kontraktu soVELO, wysyłając bezpośrednio tokeny VELO do kontraktu soVELO. W tym momencie liczba tokenów VELO posiadanych w ramach kontraktu soVELO wzrosła, ale ponieważ nie było nowych tokenów soVELO. Casting, czyli totalSupply pozostaje niezmieniony, co oznacza, że ExchangeRate obliczony według wzoru kalkulacyjnego ExchangeRate będzie w tym momencie większy.
Osoba atakująca wielokrotnie przekazywała swoje zasoby tokenów soVELO, ostatecznie innemu atakującemu, EOA 0xae4a.
Atak dla zysku
Faza zysku z ataku polega głównie na wykonaniu przez atakującego piątej transakcji propozycji i pożyczeniu tokenów VELO bezpośrednio do kontraktu soVELO poprzez pożyczki flash w celu dalszego zwiększenia kursu wymiany. Następnie atakujący użył tokena soVELO o wartości 2 na ręce, aby pożyczyć tokeny bazowe, takie jak WETH i USDC, z innych kontraktów soToken (takich jak soWETH, soUSDC itp.), a części te stały się zyskiem atakującego. Następnie atakujący udał się, aby wymienić swój token bazowy w kontrakcie soVELO. Ze względu na wzrost kursu wymiany i utratę dokładności w obliczaniu tokenów soVELO, które należy zniszczyć w celu wykorzystania, atakujący ostatecznie użył jedynie tokenu soVELO o wartości. 1. Prawie wszystkie zdeponowane wcześniej tokeny VELO zostały wykorzystane, co można rozumieć jako wykorzystanie przez atakującego dodatkowych tokenów soVELO o wartości 1 do zdobycia tokenów bazowych takich jak WETH i USDC poprzez pożyczanie od innych soTokenów. Osoba atakująca wielokrotnie powtarzała tę samą metodę i ostatecznie osiągnęła ogromne zyski.
Konkretne kroki są następujące:
Atakujący realizuje piątą transakcję w propozycji i ustala współczynnik kredytowania określony w propozycji.
Atakujący pożycza tokeny VELO o wartości „35 469 150 965 253 049 864 450 449” z puli VolatileV2 AMM - USDC/VELO, co uruchamia funkcję haka atakującego. W przypadku funkcji haka atakujący kontynuuje operację ataku.
Atakujący wysyła własne tokeny VELO do kontraktu soVELO w celu dalszego zwiększenia kursu wymiany. Obecnie w umowie soVELO znajduje się łącznie tokenów VELO o wartości „35 471 703 929 512 754 530 287 976” (suma tokenów VELO przekazanych trzykrotnie przez atakującego).
Atakujący tworzy nowy kontrakt 0xa16388a6210545b27f669d5189648c1722300b8b W konstruktorze przenosi 2 posiadane tokeny soVELO do nowo utworzonego kontraktu 0xa163 (zwanego dalej atakującym 0xa163).
Osoba atakująca 0xa163 użyła posiadanych tokenów soVELO, aby pożyczyć WETH o wartości „265 842 857 910 985 546 929” od soWETH.
Atakujący 0xa163 wywołuje funkcję „redeemUnderlying” soVELO, podając wartość wykorzystanych tokenów VELO jako „35 471 603 929 512 754 530 287 976” (prawie liczba tokenów VELO, które atakujący przeniósł wcześniej lub obciążył hipoteką w umowie soVELO). wykupAmountIn / ExchangeRate”, aby obliczyć liczbę tokenów soVELO, które należy zniszczyć, aby je wymienić.
Jak widać z funkcji „exchangeRateStoredInternal”, ponieważ _totalSupply wynosi 2 zamiast 0, należy obliczyć wartość ExchangeRate zgodnie ze wzorem „exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply”, aktualna wartość ExchangeRate wynosi. „17 735 851 964 756 377 265 143 988 000, 000 000 000 000 000”, ta wartość jest znacznie większa niż początkowa wartość kursu wymiany ustawiona na „200 000 000 000 000 000 000 000,00”.
Wartość „resemTokens” obliczona na podstawie nowego kursu wymiany wynosi „1,99”. Ze względu na zaokrąglanie w dół wartości Solidity, wartość „resemTokens” wynosi 1. Oznacza to, że atakujący 0xa163 użył tokenów soVELO o wartości 1 do wykorzystania prawie wszystkich zdeponowanych wcześniej tokenów VELO. W tym samym czasie osoba atakująca 0xa163 zarobiła również WETH o wartości „265 842 857 910 985 546 929” pożyczone od soWETH.
soVELO.redeemPodstawowe:
soVELO.exchangeRateStoredInternal:
Atakujący 0xa163 przekazał wszystkie pożyczone WETH i wykorzystane tokeny VELO atakującemu wyższego poziomu, a następnie dokonał samozniszczenia.
Osoba atakująca wywołuje funkcję „liquidateBorrow” soWETH w celu upłynnienia części aktywów pożyczonych z nowo utworzonego kontraktu 0xa163, w celu odzyskania zablokowanych tokenów soVELO o wartości 1. Obecnie atakujący posiada jedynie tokeny soVELO o wartości 1.
Osoba atakująca wywołuje funkcję „mint” soVELO, aby ponownie zastawić i wystawić tokeny soVELO w celu zebrania tokenów soVELO o wartości 2, a następnie ponownie wykonuje kroki 3-8 powyżej, aby zarobić na innych nieodchodzących tokenach.
Atakujący wykonuje krok 9 kilka razy, spłaca pożyczkę flash i wychodzi z zyskiem.
Jak 100 dolarów wykorzystuje 6,5 miliona dolarów
Po ataku użytkownik @tonyke_bot na X wybił 0.00000011 soVELO, wstawiając 1144 tokenów VELO do kontraktu soVELO w transakcji 0x0a284cd. Powodem, dla którego ta operacja może zapobiec dalszym atakom atakującego, jest to, że transakcja ta zmienia wielkość totalSupply w soVELO i liczbę posiadanych tokenów VELO totalCash, a wpływ wzrostu totalSupply na obliczenie kursu wymiany jest większy niż wpływ wzrostu totalCash W związku z tym kurs wymiany staje się mniejszy, co powoduje, że atakujący nie może już wykorzystywać utraty celności do zarabiania soVELO podczas przeprowadzania ataku, co sprawia, że atak nie jest już możliwy.
Śledzenie pieniędzy
Osoba atakująca przelała środki wkrótce po zdobyciu nielegalnych zysków. Większość środków została przesłana na cztery następujące adresy. Część miała na celu zmianę adresu w celu kontynuowania ataku, a część miała na celu pranie brudnych pieniędzy:
0x4ab93fc50b82d4dc457db85888dfdae28d29b98d
Osoba atakująca przelała na ten adres 198 WETH, po czym adres ten tą samą metodą ataku wykorzystał do uzyskania nielegalnych zysków w następujących transakcjach:
Po ataku adres przeniósł wyżej wymienione nielegalne zyski na adres 0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb.
0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb
Osoba atakująca przelała na ten adres 724277 USDC i 2353 VELO oraz wymieniła USDC na Ether. Część środków została natychmiast przeniesiona na most krzyżowy Stargate, a większość nielegalnych środków pozostała pod tym adresem:
0xbd18100a168321701955e348f03d0df4f517c13b
Osoba atakująca przesłała na ten adres kwotę 33 WETH i użyła łańcucha typu „pee chain”, aby wyprać pieniądze. Link do prania pieniędzy jest następujący:
0xbd18100a168321701955e348f03d0df4f517c13b -> 0x7e97b74252b6df53caf386fb4c54d4fb59cb6928 -> 0xc521bde5e53f537ff208970152b75a0 03093c2b4 -> 0x9f09ec563222fe52712dc413d0b7b66cb5c7c795.
0x4fac0651bcc837bf889f6a7d79c1908419fe1770
Osoba atakująca przeniosła 563 WETH na ten adres, a następnie na 0x1915F77A116dcE7E9b8F4C4E43CDF81e2aCf9C68. Obecnie nie ma dalszych działań.
Tym razem metoda prania pieniędzy zastosowana przez osobę atakującą jest stosunkowo profesjonalna, a metody wykazują tendencję do różnorodności. Dlatego też, dla nas, uczestników Web3, musimy w dalszym ciągu udoskonalać nasze możliwości w zakresie przeciwdziałania praniu pieniędzy pod względem bezpieczeństwa oraz poprawiać bezpieczeństwo projektów Defi poprzez KYT, AML i inne powiązane produkty zabezpieczające transakcje typu blockchain.
Porady dotyczące bezpieczeństwa
Utratę dokładności należy traktować poważnie. Problemy z bezpieczeństwem spowodowane utratą dokładności pojawiają się nieustannie, szczególnie w projektach Defi, gdzie utrata dokładności często prowadzi do poważnych strat finansowych. Zaleca się, aby strony projektu i audytorzy bezpieczeństwa dokładnie przejrzeli kod pod kątem utraty dokładności w projekcie i przeprowadzili testy, aby w jak największym stopniu uniknąć tej luki.
Zaleca się, aby utworzenie rynku podobnego do cToken w Compound i pierwsza operacja castingu kredytu hipotecznego były wykonywane przez uprzywilejowanych użytkowników, aby uniknąć obsługi przez atakujących i tym samym manipulacji kursem wymiany.
Gdy w umowie występują kluczowe zmienne zależne od wartości „ this.balance ” lub „ token.balanceOf() ”, należy dokładnie rozważyć warunki zmiany kluczowej zmiennej, np. czy dozwolone jest bezpośrednio przenieść natywną walutę lub tokeny do kontraktu. Zmień wartość zmiennej, czy też wartość zmiennej można zmienić jedynie poprzez wywołanie określonej funkcji.
Ten artykuł został napisany wspólnie przez Carę z ZAN Team (konto X @Cara6289) i XiG (konto X @SHXiGi).