Książka: „Omijanie warstwy zerowej: dlaczego izolowane bezpieczeństwo nie oznacza żadnego bezpieczeństwa”
Autor: Krzysztof Urbański, członek zespołu L2BEAT
Opracowano przez: Babywhale, Foresight News
Od samego początku L2BEAT włożył wiele wysiłku w analizę i zrozumienie zagrożeń związanych z protokołami warstwy 2. Zawsze działamy w najlepszym interesie naszych użytkowników i ekosystemu i dokładamy wszelkich starań, aby być bezstronnym, niezależnym nadzorcą, nie pozwalając, aby nasze osobiste preferencje dotyczące projektów lub powiązanych zespołów wpływały na fakty. Dlatego nawet jeśli szanujemy czas i wysiłek, jaki zespół projektowy wkłada w projekt, możemy „podnieść alarm” lub wskazać na nasze obawy dotyczące potencjalnego ryzyka związanego z niektórymi protokołami. Wczesne prowadzenie dyskusji na temat bezpieczeństwa pozwala lepiej przygotować cały ekosystem na potencjalne zagrożenia i wcześniej reagować na wszelkie podejrzane zachowania.
Dzisiaj chcielibyśmy omówić wspólny model bezpieczeństwa dla aplikacji międzyłańcuchowych. Obecnie istnieją dwa modele bezpieczeństwa: bezpieczeństwo współdzielone i bezpieczeństwo niezależnych aplikacji. Wspólne bezpieczeństwo jest jak wszystkie Rollupy. Samodzielne zabezpieczenia aplikacji są wykorzystywane głównie w projektach typu „omnichain”, które korzystają głównie z warstwy LayerZero.
Bezpieczeństwo wspólne a bezpieczeństwo niezależne

Bezpieczeństwo współdzielone odnosi się do konkretnego tokena lub aplikacji działającej na danej infrastrukturze i zamiast swobodnie wybierać model bezpieczeństwa, musi spełniać wszelkie wymogi bezpieczeństwa narzucane przez infrastrukturę. Na przykład optymistyczne pakiety zbiorcze zazwyczaj nakładają 7-dniowe okno końcowe — aplikacja działająca na takich pakietach zbiorczych nie może po prostu zignorować ani skrócić tego okresu. Chociaż może się to wydawać przeszkodą, istnieje ku temu powód. Okres ten daje użytkownikom pewność bezpieczeństwa, że niezależnie od wewnętrznej polityki bezpieczeństwa aplikacji, której należy przestrzegać, aplikacja może jedynie wzmacniać bezpieczeństwo Rollupów, a nie je osłabiać.
Niezależne bezpieczeństwo oznacza, że każda aplikacja jest odpowiedzialna za określenie swojego bezpieczeństwa i nie jest w żaden sposób ograniczana przez infrastrukturę. Na początku może się to wydawać dobrym pomysłem, w końcu twórca aplikacji wie najlepiej, jakich środków bezpieczeństwa może wymagać aplikacja. Jednocześnie jednak 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 zasad bezpieczeństwa, mogą je również zmienić w dowolnym momencie. Dlatego nie wystarczy ocenić ryzyko raz dla każdej aplikacji; należy ją oceniać za każdym razem, gdy zmieniają się zasady aplikacji.
Problemy

Wierzymy, że niezależny model bezpieczeństwa, w którym każda aplikacja może dowolnie definiować swoją politykę bezpieczeństwa, stwarza poważne problemy bezpieczeństwa. Po pierwsze, zwiększa ryzyko dla użytkowników końcowych, ponieważ muszą oni weryfikować ryzyko w przypadku każdej aplikacji, z której zamierzają korzystać.
Samodzielne zabezpieczenia zwiększają również ryzyko dla aplikacji korzystających z tego modelu, na przykład dodając dodatkowe ryzyko związane ze zmianami zasad bezpieczeństwa — jeśli osoba atakująca zmieni model zabezpieczeń aplikacji, równie dobrze mogłaby go po prostu wyłączyć, tym samym tracąc pieniądze lub narażając je na ryzyko w jakikolwiek sposób zaatakować w inny sposób. Na aplikacji nie ma żadnych dodatkowych warstw zabezpieczeń zapobiegających atakom.
Ponadto, ponieważ zasady bezpieczeństwa mogą zmieniać się w dowolnym momencie i na bieżąco, monitorowanie aplikacji w czasie rzeczywistym i informowanie użytkowników o zagrożeniach jest prawie niemożliwe.

Uznaliśmy, że jest to podobne do możliwości aktualizacji inteligentnych kontraktów, przed którą ostrzegaliśmy w L2BEAT. Informujemy użytkowników o mostach typu Rollup i cross-chain, które posiadają w swoich inteligentnych kontraktach mechanizmy możliwości aktualizacji, a także dokładne mechanizmy zarządzania możliwością aktualizacji w każdym przypadku. Jest to już dość skomplikowane, a zastosowanie oddzielnego modelu bezpieczeństwa mnoży tę liczbę, przez co skuteczne śledzenie jest prawie niemożliwe.
Właśnie dlatego uważamy, że samodzielny model bezpieczeństwa sam w sobie stanowi zagrożenie bezpieczeństwa i zakładamy, że każdą aplikację, która domyślnie będzie korzystać z tego modelu, należy uważać za ryzykowną, dopóki nie zostanie udowodnione, że jest inaczej.
Udowodnij, że istnieją luki w zabezpieczeniach
Postanowiliśmy przetestować naszą hipotezę w sieci głównej. Do eksperymentów wybrano framework LayerZero, ponieważ jest to jedno z najpopularniejszych samodzielnych rozwiązań skupiających się na bezpieczeństwie. Wdrożyliśmy bezpieczny token omnichain, a później zaktualizowaliśmy konfigurację zabezpieczeń, aby umożliwić złośliwe wycofanie tokena. Kod tokena oparty jest na przykładach dostarczonych przez LayerZero i jest bardzo podobny lub identyczny z wieloma innymi tokenami i aplikacjami omnichain wdrażanymi w prawdziwym życiu.
Zanim jednak przejdziemy do szczegółów, rzućmy okiem na to, jak wygląda model bezpieczeństwa LayerZero.

Jak wskazuje LayerZero w swojej białej księdze, jego „bezufna komunikacja między łańcuchami” opiera się na dwóch niezależnych aktorach (wyroczniach i przekaźnikach) działających razem w celu zapewnienia bezpieczeństwa protokołu.
LayerZero stwierdza na swojej stronie internetowej, że jego podstawową koncepcją są „aplikacje użytkownika działające na ULN (UltraLightNode), konfigurowalne terminale on-chain”. Komponent on-chain LayerZero opiera się na dwóch zewnętrznych komponentach poza łańcuchem do przekazywania wiadomości między łańcuchami – wyroczniami i przekaźnikami.
Za każdym razem, gdy jakikolwiek komunikat M jest wysyłany z łańcucha A do łańcucha B, zachodzą następujące dwie operacje:
Najpierw wyrocznia czeka, aż transakcja wysyła wiadomość M w łańcuchu A, a następnie zapisuje odpowiednie informacje w łańcuchu B, takie jak wartość skrótu nagłówka bloku łańcucha A zawierającego wiadomość M (dokładna wartość między różnymi łańcuchami/wyroczniami Format może się różnić).
Następnie przekaźnik wysyła „dowód” (taki jak Merkle Proof) do łańcucha B, potwierdzając, że przechowywany nagłówek bloku zawiera komunikat M.
LayerZero zakłada, że przekaźniki i wyrocznie są niezależnymi, uczciwymi uczestnikami. Jednakże LayerZero stwierdziło również w białej księdze, że jeśli to założenie nie zostanie spełnione, na przykład przekaźnik i wyrocznia zmową, w wyniku czego „zarówno nagłówek bloku dostarczony przez wyrocznię, jak i dowód transakcji dostarczony przez przekaźnik będą nieważne, ale nadal pasuje.”
LayerZero twierdzi, że „projekt LayerZero eliminuje możliwość zmowy”. Jednak w rzeczywistości stwierdzenie to jest błędne (udowodniliśmy to w eksperymentach pokazanych poniżej), ponieważ każda aplikacja użytkownika może definiować własne przekaźniki i wyrocznie. LayerZero nie gwarantuje z założenia, że te komponenty są niezależne i nie mogą ze sobą współdziałać; zapewnienie takich gwarancji leży w gestii aplikacji użytkownika. LayerZero nie ma mechanizmu zatrzymującego aplikacje, jeśli zdecydują się je złamać.
Dodatkowo domyślnie wszystkie aplikacje użytkownika mogą w dowolnym momencie zmieniać przekaźniki i wyrocznie, całkowicie na nowo definiując założenia bezpieczeństwa. Dlatego jednorazowe sprawdzenie bezpieczeństwa danej aplikacji nie wystarczy, gdyż po sprawdzeniu może się to zmienić w każdej chwili, co pokażemy w naszych eksperymentach.
eksperymentalny projekt
Na potrzeby naszych eksperymentów zdecydowaliśmy się stworzyć prosty token omnichain, CarpetMoon, który działa zarówno na Ethereum, jak i Optimism i wykorzystuje LayerZero do komunikacji między dwoma łańcuchami.
Nasz token początkowo korzysta z domyślnego modelu bezpieczeństwa zapewnianego przez LayerZero, dzięki czemu jest identyczny z dużymi (być może nie wszystkimi) aktualnie wdrażanymi aplikacjami LayerZero. Dlatego jest ogólnie tak samo bezpieczna jak każda inna moneta korzystająca z LayerZero.
Najpierw wdrażamy nasz kontrakt tokenowy na Ethereum i Optimism:
https://ethtx.info/mainnet/0xf4d1cdabb6927c363bb30e7e65febad8b9c0f6f76f1984cd74c7f364e3ab7ca9/
https://optimistic.etherscan.io/tx/0xf41389d71fa3942de5225efb067072728c6c6de56c241574187781db7c73d221
Następnie konfigurujemy 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
Token został wdrożony i wygląda dokładnie tak, jak każdy inny token omnichain korzystający z LayerZero, z domyślną konfiguracją i nie ma w nim nic podejrzanego.

Udostępniliśmy 1 miliard tokenów CarpetMoon w Ethereum naszej „użytkownikce testowej” Alice.
https://ethtx.info/mainnet/0x7e2faa8426dacae92830efbf356ca2da760833eca28e652ff9261fc03042b313/

Teraz Alicja używa LayerZero do połączenia tych tokenów z Optymizmem.
Blokujemy tokeny w umowie depozytowej na Ethereum:
https://ethtx.info/mainnet/0xe4dc3757b86bfda8e7baddc088fb1a599e083ed77034c29e5dd8bd11f1e17771/.
Wiadomość zawierająca transakcję jest przekazywana do Optimism poprzez LayerZero:
https://layerzeroscan.com/101/address/0xc6005ccc1de4b300d538903b74848bff881d5dc5/message/111/address/0x201fe0d843b546f2e24d4c8444318d1c71b7nonced10d/.

Tokeny międzyłańcuchowe są bite na Optymizmie, a Alicja posiada teraz 1 miliard tokenów MoonCarpet na Optymizmie:
https://optimistic.etherscan.io/tx/0x5388ced88cf562acafff82d6798f791b0b38b90ee106df9bf91c0d86306ec302.
Wszystko działa zgodnie z oczekiwaniami, Alicja krzyżuje tokeny i widzi, że w umowie depozytowej na Ethereum znajduje się 1 miliard tokenów MoonCarpet i 1 miliard tokenów MoonCarpet na jej koncie w Optimism. Aby jednak upewnić się, że wszystko jest w porządku, przeniosła połowę swoich tokenów z powrotem do Ethereum.

Zaczynamy od transakcji na Optimism, która spaliła 500 milionów tokenów:
https://optimistic.etherscan.io/tx/0x118a57106488ad0bae1f3b920b1fd98b187752ad966f3a901fc53cff47f2097f.
Informacja o transakcji przekazywana jest 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 zwróconych z umowy depozytowej na adres Alicji:
https://etherscan.io/tx/0x27702e07a65a9c6a7d1917222799ddb13bb3d05159d33bbeff2ca1ed414f6a18.
Jak dotąd wszystko działa dobrze i dokładnie tak, jak zakładano. Alicja sprawdziła, czy może łączyć tokeny krzyżowo z Ethereum do Optymizmu i z powrotem, nie ma powodu martwić się o swoje tokeny MoonCarpet.
Ale hipotetycy mają swoje własne problemy — na przykład zespół stojący za naszym tokenem napotyka problemy, a zły Bob uzyskuje dostęp do konfiguracji LayerZero naszej aplikacji.

W ten sposób Bob może zmienić wyrocznie i przekaźniki z komponentów domyślnych na komponenty, które kontroluje.
Należy zaznaczyć, że jest to mechanizm przewidziany dla każdej aplikacji korzystającej z LayerZero i zakorzeniony w architekturze LayerZero. Nie jest to żaden backdoor, lecz standardowy mechanizm.
Zatem Bob zmienia wyrocznię w EOA pod swoją kontrolą:
https://ethtx.info/mainnet/0x4dc84726da6ca7d750eef3d33710b5f63bf73cbe03746f88dd8375c3f4672f2f/.
Zmieniono także wzmacniacz:
https://ethtx.info/mainnet/0xc1d7ba5032af2817e95ee943018393622bf54eb87e6ff414136f5f7c48c6d19a/.
Teraz dzieje się coś dziwnego. Ponieważ wyrocznia i przekaźnik są teraz pod pełną kontrolą Boba, jest on w stanie ukraść tokeny Alicji. Mimo że nie podjęto żadnych działań w sprawie Optimism (tokeny MoonCarpet nadal znajdowały się w portfelu Alicji), Bob był w stanie przekonać inteligentny kontrakt MoonCarpet na Ethereum (przy użyciu mechanizmu LayerZero), że zniszczył tokeny w drugim łańcuchu i był w stanie wypłacić tokeny z tokena MoonCarpet na Ethereum.

Najpierw aktualizuje skrót bloku Ethereum za pomocą kontrolowanej przez siebie wyroczni:
https://ethtx.info/0xde2edee2cc7f070120e96c9df90d86696970befcfc221e18c6ac4168bb5b1d92/.

Teraz może wypłacić pozostałe tokeny z umowy depozytowej:
https://ethtx.info/0xda695f374b375d5372efeca37aae4c5a17f114d5a76db1e86edebb0924bcdcc7/.

Wyniki eksperymentalne
Alicja nawet nie wie, dlaczego i kiedy wystąpił błąd. Nagle jej token MoonCarpet na Optymizmie nie był już wspierany przez tokeny na Ethereum.
Inteligentnej umowy nie można aktualizować i działa zgodnie z oczekiwaniami. Jedyną podejrzaną aktywnością są zmiany w wyroczni i przekaźnikach, ale jest to zwykły mechanizm wbudowany w LayerZero, więc Alicja nawet nie wie, czy ta zmiana jest zamierzona. Nawet jeśli Alicja dowie się o zmianie, będzie już za późno – atakujący może wyssać środki, zanim będzie mogła zareagować.
LayerZero nie może nic zrobić - to wszystko są wydajne implementacje ich mechanizmów, nad którymi nie mają kontroli. Teoretycznie same aplikacje mogłyby uniemożliwić sobie zmianę wyroczni i przekaźników, ale według naszej wiedzy żadna wdrożona aplikacja tego nie zrobiła.
Przeprowadziliśmy ten eksperyment, aby sprawdzić, czy ktoś to zauważył, ale zgodnie z oczekiwaniami nikt tego nie zauważył. Skuteczne monitorowanie wszystkich aplikacji zbudowanych przy użyciu LayerZero w celu sprawdzenia, czy zmieniły się ich zasady bezpieczeństwa i powiadomienia użytkowników, gdy to nastąpi, jest prawie niemożliwe.
Nawet jeśli komuś uda się na czas odkryć, że wyrocznie i przekaźniki uległy zmianie i stworzyły zagrożenie dla bezpieczeństwa, będzie już za późno. Ponieważ nowe wyrocznie i przekaźniki mogą teraz swobodnie wybierać, które wiadomości mają być dostarczane lub po prostu wyłączać komunikację między łańcuchami, użytkownicy zazwyczaj niewiele mogą z tym zrobić. Nasze eksperymenty wyraźnie pokazują, że nawet jeśli Alicja zauważy zmianę konfiguracji aplikacji, nie może wiele zrobić ze swoimi tokenami międzyłańcuchowymi – nowe wyrocznie i przekaźniki nie są już akceptowane w oryginalnej wiadomości łańcucha komunikacyjnego, więc wiadomość nie zostanie zwrócona do Ethereum .
podsumowując

Jak widzimy, mimo że nasz token został zbudowany przy użyciu LayerZero i wykorzystał jego mechanikę zgodnie z przeznaczeniem, udało nam się ukraść środki z depozytu tokena. Oczywiście jest to wina aplikacji (w naszym przypadku tokena CarpetMoon), a nie samego LayerZero, ale świadczy to o tym, że samo LayerZero nie daje żadnych gwarancji bezpieczeństwa.
Kiedy LayerZero opisuje swój model bezpieczeństwa dotyczący wyroczni i przekaźników, zakłada, że właściciel aplikacji (lub ktokolwiek posiada klucz prywatny) nie zrobi nic nierozsądnego. Jednak w środowisku kontradyktoryjnym założenie to jest błędne. Ponadto wymaga od użytkowników zaufania twórcy aplikacji jako zaufanej stronie trzeciej.
W praktyce więc nie można przyjmować żadnych założeń co do bezpieczeństwa aplikacji zbudowanych przy użyciu 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ę od PR-u, w którym planowaliśmy umieścić wszystkie tokeny omnichain na stronie L2BEAT – ciężko nam było dowiedzieć się, jak ocenić ich ryzyko. Analizując ryzyko wpadliśmy na pomysł eksperymentowania.
Jeśli L2BEAT zostałby uruchomiony, konsekwencją byłoby umieszczenie alertów w każdej aplikacji zbudowanej przy użyciu LayerZero, aby ostrzec o możliwych zagrożeniach bezpieczeństwa. Chcieliśmy jednak przeprowadzić szerszą dyskusję na temat modeli bezpieczeństwa, ponieważ uważamy, że samodzielne bezpieczeństwo to model, którego należy unikać, szczególnie w naszej branży.
Wierzymy, że w miarę jak niezależne modele bezpieczeństwa, takie jak LayerZero, staną się coraz bardziej popularne, coraz więcej projektów będzie je nadużywać, powodując ogromne szkody i zwiększając niepewność w całej branży.
