Omijanie warstwy zero

Jan 05 2023
Od początku L2BEAT wkładamy wiele wysiłku w analizę i zrozumienie zagrożeń związanych z protokołami L2. Dokładamy wszelkich starań, aby być bezstronnym, niezależnym strażnikiem, działającym w najlepszym interesie użytkowników i ekosystemu.

Od początku L2BEAT wkładamy wiele wysiłku w analizę i zrozumienie zagrożeń związanych z protokołami L2. Dokładamy wszelkich starań, aby być bezstronnym, niezależnym strażnikiem, działającym w najlepszym interesie użytkowników i ekosystemu. Nie pozwalamy, aby nasze osobiste preferencje dotyczące projektu lub zaangażowanego zespołu stanęły na przeszkodzie. Dlatego często zdarza się, że musimy włączać czerwone alerty lub wskazywać nasze obawy w różnych protokołach, mimo że cenimy czas i pracę wkładaną przez poszczególne zespoły w ich projekty. Wczesne prowadzenie dyskusji związanych z bezpieczeństwem pozwala całemu ekosystemowi lepiej przygotować się na potencjalne zagrożenia i wcześniej reagować na wszelkie podejrzane zachowania.

Dzisiaj chcielibyśmy rozpocząć debatę na temat współdzielonych modeli bezpieczeństwa aplikacji międzyłańcuchowych. Obecnie istnieją dwa podejścia: bezpieczeństwo współdzielone a bezpieczeństwo poszczególnych aplikacji. Pierwsze, współdzielone bezpieczeństwo, jest wykorzystywane na przykład we wszystkich rollupach. Drugie, bezpieczeństwo per-aplikacyjne, wykorzystywane jest w projektach „omnichain”. Najlepszym przykładem takiego projektu jest LayerZero.

Zabezpieczenia współdzielone a zabezpieczenia izolowane

Przez współdzielone bezpieczeństwo rozumiemy to, że określone tokeny lub aplikacje działające na danej infrastrukturze nie wybierają swobodnie swojego modelu bezpieczeństwa. Zamiast tego muszą przestrzegać wszelkich wymogów bezpieczeństwa nałożonych przez infrastrukturę. Na przykład optymistyczne pakiety zbiorcze zazwyczaj narzucają 7-dniowy termin ważności — aplikacje działające na takich pakietach nie mogą po prostu zignorować ani skrócić tego okresu. Może się to wydawać przeszkodą, ale jest to przeszkoda postawiona nie bez powodu. Pozwala zapewnić użytkownikom gwarancję bezpieczeństwa, której mogą oczekiwać od dowolnej aplikacji, której używają w tym pakiecie zbiorczym, bez względu na to, jaka jest wewnętrzna polityka bezpieczeństwa aplikacji. Aplikacja może tylko wzmocnić politykę podsumowań, a nie ją osłabić.

Przez izolowane bezpieczeństwo rozumiemy, że każda aplikacja jest odpowiedzialna za zdefiniowanie swojego bezpieczeństwa, nie będąc w żaden sposób ograniczana przez infrastrukturę. Na początku może się to wydawać dobrym pomysłem. W końcu twórcy aplikacji najlepiej wiedzą, jakich środków bezpieczeństwa może wymagać aplikacja. Ale jednocześnie przenosi odpowiedzialność za ocenę ryzyka związanego z polityką bezpieczeństwa każdej aplikacji na użytkownika końcowego. Ponadto, jeśli twórcy aplikacji mają swobodę wyboru swoich zasad dotyczących aplikacji, mogą również zdecydować się na ich zmianę w dowolnym momencie. Dlatego nie wystarczy raz ocenić ryzyka dla każdej aplikacji, należy je oceniać za każdym razem, gdy zmieniają się zasady aplikacji.

Problem

Uważamy, że izolowany model bezpieczeństwa, w którym każda aplikacja może swobodnie definiować swoją politykę bezpieczeństwa, stwarza poważne obawy dotyczące bezpieczeństwa. Przede wszystkim zwiększa ryzyko dla użytkowników końcowych, ponieważ muszą oni osobno sprawdzać ryzyko związane z każdą aplikacją, z której zamierzają korzystać.

Zwiększa to również ryzyko dla aplikacji korzystających z takiego modelu. Izolowane zabezpieczenia dodają dodatkowe ryzyko związane ze zmianą polityki bezpieczeństwa — jeśli atakujący zmieni model bezpieczeństwa aplikacji, równie dobrze może ją po prostu wyłączyć, dając możliwość drenażu środków lub niewłaściwego wykorzystania ich w inny sposób. Na aplikacji nie ma dodatkowej warstwy bezpieczeństwa, która chroniłaby przed nadużyciami.

Co więcej, przy możliwości natychmiastowej zmiany zasad bezpieczeństwa w dowolnym momencie, codzienne monitorowanie aplikacji i informowanie użytkowników o zagrożeniach staje się praktycznie niemożliwe.

Uważamy, że jest to podobne do możliwości aktualizacji inteligentnych kontraktów. Ostrzegamy już przed tym na L2BEAT . Informujemy użytkowników o rollupach i pomostach, które mają mechanizmy aktualizacji w swoich smart kontraktach, a także o dokładnym mechanizmie rządzącym aktualizacją w każdym przypadku. Jest to już dość złożone, a przy izolowanym modelu bezpieczeństwa mnoży się to dla każdej aplikacji, co prawie uniemożliwia skuteczne śledzenie.

Dlatego uważamy izolowany model bezpieczeństwa za zagrożenie bezpieczeństwa samo w sobie i postulujemy, aby każdą aplikację korzystającą z takiego modelu traktować domyślnie jako ryzykowną, dopóki nie zostanie udowodnione, że jest inaczej.

Plan

Postanowiliśmy przetestować nasze założenia w realnym świecie, w sieci głównej. Do eksperymentu wybrano framework LayerZero, ponieważ jest to jedno z najpopularniejszych rozwiązań wykorzystujących w swej istocie izolowane zabezpieczenia. Wdrożyliśmy bezpieczny token omnichain, a następnie zaktualizowaliśmy konfigurację zabezpieczeń, co pozwoliło na wycofanie złośliwych tokenów. Kod tokena oparty jest na przykładach dostarczonych przez LayerZero i jest bardzo podobny lub identyczny z wieloma innymi tokenami i aplikacjami omnichain wdrożonymi w produkcji.

Ale zanim zagłębimy się w szczegóły, rzućmy okiem na to, jak wygląda model bezpieczeństwa LayerZero.

Jak wyraźnie stwierdzono w białej księdze LayerZero, jej „niezawodna komunikacja między łańcuchami” opiera się na dwóch niezależnych aktorach (wyroczni i przekaźniku) działających wspólnie w celu zapewnienia bezpieczeństwa protokołu.

Jak stwierdza LayerZero na swojej stronie internetowej, jego podstawową koncepcją jest to, że jest to „konfigurowalny punkt końcowy w łańcuchu aplikacji użytkownika, który obsługuje ULN (UltraLightNode)”. Komponenty on-chain LayerZero opierają się na dwóch zewnętrznych podmiotach poza łańcuchem, które przekazują wiadomości między łańcuchami — Oracle i Relayer.

Ilekroć jakakolwiek wiadomość M jest wysyłana z łańcucha A do łańcucha B, mają miejsce następujące dwie akcje:

  • najpierw Oracle czeka, aż transakcja wysyłająca komunikat M w łańcuchu A zostanie sfinalizowana, a następnie zapisuje w łańcuchu B zobowiązanie dla pakietu komunikatów, na przykład skrót nagłówka bloku (dokładny format może się różnić w zależności od różnych łańcuchów/wyroczni) w łańcuchu A zawierającym tę wiadomość M
  • następnie Relayer wysyła do łańcucha B „dowód” (na przykład Merkle Proof), że przechowywany nagłówek zawiera wiadomość M

LayerZero twierdzi, że „projekt LayerZero eliminuje możliwość zmowy”. Ale w rzeczywistości to stwierdzenie nie jest prawdziwe (co udowadniamy w eksperymencie pokazanym poniżej), ponieważ każda aplikacja użytkownika może zdefiniować własny Relayer i Oracle. LayerZero nie gwarantuje z założenia, że ​​te komponenty są niezależne i że nie mogą działać w zmowie. Zapewnienie tych gwarancji zależy od aplikacji użytkownika. A jeśli aplikacja zdecyduje się je złamać, nic w mechanice LayerZero nie może jej przed tym powstrzymać.

Co więcej, domyślnie wszystkie aplikacje użytkownika mogą w dowolnym momencie zmienić Relayer i Oracle, całkowicie redefiniując założenia bezpieczeństwa. Nie wystarczy więc raz sprawdzić bezpieczeństwa danej aplikacji, ponieważ po sprawdzeniu mogło się ono zmienić w dowolnym momencie, co pokażemy w naszym eksperymencie.

Eksperyment

W naszym eksperymencie zdecydowaliśmy się stworzyć prosty token omnichain, CarpetMoon, działający zarówno na Ethereum, jak i Optimism, wykorzystując ZeroLayer do komunikacji między obydwoma łańcuchami.

Nasz token początkowo korzysta z domyślnego modelu bezpieczeństwa zapewnianego przez LayerZero, więc wygląda tak samo jak większość (jeśli nie wszystkie) obecnie wdrożonych aplikacji LayerZero. W związku z tym jest ogólnie tak bezpieczny, jak każdy inny token korzystający z LayerZero.

Najpierw wdrażamy nasze kontrakty tokenowe zarówno na Ethereum, jak i na Optimism:
https://ethtx.info/mainnet/0xf4d1cdabb6927c363bb30e7e65febad8b9c0f6f76f1984cd74c7f364e3ab7ca9/
https://optimistic.etherscan.io/tx/0xf41389d71fa3942de5225efb067072728c6c6de56c241574187781db7c73d221

Skonfigurowaliśmy routing tak, aby LayerZero wiedział, który kontrakt odpowiada któremu w obu łańcuchach:
https://ethtx.info/mainnet/0x19d78abb03179969d6404a7bd503148b4ac14d711f503752495339c96a7776e9/
https://optimistic.etherscan.io/tx/0x037b1bad33faa5607bb5835460a1d5caaf3a147dc3a09762ac7703befcdb3c3c

Więc token jest skonfigurowany, wygląda dokładnie tak, jak wszystkie inne tokeny omnichain używające LayerZero, z domyślną konfiguracją, nic podejrzanego.

Dostarczamy naszemu testowemu użytkownikowi, nazwijmy go Alice, tokeny testowe, więc Alicja ma 1B tokenów CarpetMoon na Ethereum:
https://ethtx.info/mainnet/0x7e2faa8426dacae92830efbf356ca2da760833eca28e652ff9261fc03042b313/

Teraz Alice łączy te tokeny z optymizmem za pomocą LayerZero.

Tokeny zamykamy w depozycie na Ethereum:
https://ethtx.info/mainnet/0xe4dc3757b86bfda8e7baddc088fb1a599e083ed77034c29e5dd8bd11f1e17771/

Wiadomość z transakcją jest dostarczana do Optimism przez LayerZero:
https://layerzeroscan.com/101/address/0xc6005ccc1de4b300d538903b74848bff881d5dc5/message/111/address/0x201fe0d843b546f2e24d4c8444318d1c71b7d10d/nonce/1

I tokeny mostkowe są wybijane na Optimism, Alice ma teraz 1B tokenów MoonCarpet na Optimism:
https://optimistic.etherscan.io/tx/0x5388ced88cf562acafff82d6798f791b0b38b90ee106df9bf91c0d86306ec302

Ok, więc wszystko poszło zgodnie z oczekiwaniami, Alice zmostkowała swoje tokeny i zobaczyła, że ​​w depozycie na Ethereum jest 1B tokenów MoonCarpet i 1B tokenów MoonCarpet na jej koncie w Optimism. Ale aby upewnić się, że wszystko działa poprawnie, przenosi połowę tokenów (500M MoonCarpet) z powrotem do Ethereum.

Zaczynamy więc od transakcji wypalania 500M tokenów na Optimism:
https://optimistic.etherscan.io/tx/0x118a57106488ad0bae1f3b920b1fd98b187752ad966f3a901fc53cff47f2097f

Informacje o tej transakcji są przekazywane do Ethereum:
https://layerzeroscan.com/111/address/0x201fe0d843b546f2e24d4c8444318d1c71b7d10d/message/101/address/0xc6005ccc1de4b300d538903b74848bff881d5dc5/nonce/1

Zgodnie z oczekiwaniami, 500 milionów tokenów MoonCarpet zostało dostarczonych z powrotem na adres Alice z depozytu:
https://etherscan.io/tx/0x27702e07a65a9c6a7d1917222799ddb13bb3d05159d33bbeff2ca1ed414f6a18

Do tej pory wszystko działa dobrze, dokładnie tak, jak zakładano. Alice sprawdziła, czy może przenosić tokeny z Ethereum do Optimism iz powrotem, nie ma powodu, by bać się o swoje tokeny MoonCarpet.

Ale powiedzmy, że coś pójdzie nie tak — na przykład zespół stojący za naszym tokenem zostanie przejęty, a przestępca Bob uzyska dostęp do konfiguracji LayerZero dla naszej aplikacji.

Mając taki dostęp, Bob może zmienić Wyrocznię i Przekaźnik z domyślnych na te, które kontroluje.

Należy pamiętać, że jest to mechanizm dostarczany każdej aplikacji korzystającej z LayerZero, zakorzeniony w architekturze LayerZero, nie jest to żaden rodzaj backdoora, ale raczej standardowy mechanizm.

Więc Bob zmienia Wyrocznię w EOA pod jego kontrolą:
https://ethtx.info/mainnet/0x4dc84726da6ca7d750eef3d33710b5f63bf73cbe03746f88dd8375c3f4672f2f/

I robi to samo z przekaźnikiem:
https://ethtx.info/mainnet/0xc1d7ba5032af2817e95ee943018393622bf54eb87e6ff414136f5f7c48c6d19a/

A teraz dzieją się dziwne rzeczy. Ponieważ Oracle i Relayer są teraz pod pełną kontrolą Boba, jest on w stanie ukraść tokeny Alice. Mimo że na Optimism nie ma miejsca żadna akcja (tokeny MoonCarpet wciąż są tam w portfelu Alicji) Bob jest w stanie przekonać smart kontrakt MoonCarpet na Ethereum (za pomocą mechanizmów LayerZero), że spalił tokeny w innym łańcuchu i jest w stanie wypłacić tokeny MoonCarpet na Ethereum.

Najpierw aktualizuje blockhash w Ethereum za pomocą nieuczciwej Oracle:
https://ethtx.info/0xde2edee2cc7f070120e96c9df90d86696970befcfc221e18c6ac4168bb5b1d92/

A teraz może wypłacić pozostałe żetony z depozytu:
https://ethtx.info/0xda695f374b375d5372efeca37aae4c5a17f114d5a76db1e86edebb0924bcdcc7/

Wynik

Alicja nawet nie będzie wiedziała, dlaczego i kiedy stało się coś złego. Nagle jej tokeny MoonCarpet w Optimism nie są już wspierane przez tokeny w Ethereum.

Inteligentne kontrakty nie podlegają aktualizacji i działają zgodnie z przeznaczeniem. Jedyną podejrzaną aktywnością jest zmiana Oracle i Relayer, ale jest to zwykły mechanizm wbudowany w LayerZero, więc Alice nie może nawet wiedzieć, czy ta zmiana była zamierzona, czy nie. A nawet gdyby Alicja dowiedziała się o tej zmianie, byłoby już za późno — atakujący jest w stanie ukraść środki, zanim ona zdąży zareagować.

I tutaj LayerZero nie mogło pomóc — to wszystko były prawidłowe wykonania ich mechanizmów, których nie mogą już kontrolować. Teoretycznie sama aplikacja może blokować się przed zmianą Oracle i Relayera, ale o ile nam wiadomo, żadna z już wdrożonych aplikacji tego nie zrobiła.

Przeprowadziliśmy ten eksperyment, aby sprawdzić, czy ktoś to zauważy, ale tak jak się spodziewaliśmy, nikt tego nie zauważył. Praktycznie niemożliwe jest skuteczne monitorowanie wszystkich aplikacji zbudowanych za pomocą LayerZero, aby sprawdzić, czy ich polityka bezpieczeństwa się nie zmieniła i ostrzec użytkowników, jeśli tak się stanie.

Nawet jeśli udałoby się dogonić zmiany Oracle i Relayer w sposób stwarzający zagrożenie bezpieczeństwa, kiedy to się dzieje, jest już za późno. Ponieważ nowe Oracle i Relayer mogą teraz swobodnie cenzurować lub po prostu wyłączyć komunikację między łańcuchami, użytkownicy zwykle nie mogą nic z tym zrobić. Jest to wyraźnie pokazane w naszym eksperymencie, ponieważ nawet jeśli Alicja zauważy zmianę w konfiguracji aplikacji, nie może wiele zrobić ze swoimi zmostkowanymi tokenami — nowa Oracle i Relayer nie nasłuchują już w oryginalnym łańcuchu, więc nie przekazują wiadomości z powrotem do Ethereum.

Wnioski i wezwanie do działania

Jak mogliśmy zobaczyć powyżej, mimo że nasz token został zbudowany przy użyciu LayerZero i wykorzystał jego mechanikę zgodnie z przeznaczeniem, byliśmy w stanie ukraść środki z depozytu tokenów. Oczywiście była to wina aplikacji (w naszym przypadku tokena CarpetMoon), a nie samego LayerZero, ale to dowodzi, że LayerZero samo w sobie nie daje żadnych gwarancji bezpieczeństwa .

Kiedy LayerZero opisuje swój model bezpieczeństwa w odniesieniu do Oracle i Relayer, zakłada, że ​​właściciele aplikacji (lub ktoś posiadający ich klucze prywatne) nie zrobią nic irracjonalnego. Ale to założenie jest błędne w środowisku przeciwnika. Ponadto wymaga od użytkowników zaufania do właścicieli aplikacji jako zaufanej strony trzeciej.

W praktyce w rezultacie nie można robić żadnych założeń co do bezpieczeństwa aplikacji zbudowanych z wykorzystaniem LayerZero — każdą aplikację należy uważać za ryzykowną, dopóki nie zostanie udowodnione, że jest inaczej.

Właściwie cała historia zaczęła się dla nas od PR, w ramach którego planowaliśmy umieścić wszystkie tokeny omnichain na stronie L2BEAT — trudno nam było wymyślić, jak ocenić związane z nimi ryzyko. Analizując wektory ryzyka, wpadliśmy na pomysł naszego eksperymentu.

Konsekwencje dla L2BEAT są takie, że musimy umieszczać alerty na wierzchu każdej aplikacji zbudowanej przy użyciu LayerZero, ostrzegające o możliwych zagrożeniach bezpieczeństwa. Chcielibyśmy jednak rozpocząć szerszą dyskusję na temat modeli bezpieczeństwa, ponieważ uważamy, że izolowane bezpieczeństwo jest antywzorcem, którego należy unikać, zwłaszcza w naszej przestrzeni.

Jesteśmy przekonani, że wraz ze wzrostem popularności izolowanych modeli bezpieczeństwa, takich jak LayerZero, będzie coraz więcej projektów wykorzystujących je, powodując wiele szkód i wzbudzając niepewność w całej branży.