Autor: CertiK

 

Dříve tým CertiK objevil řadu zranitelností v blokovém řetězci Sui. Mezi těmito zranitelnostmi vyniká nová zranitelnost s velkým dopadem. Tato chyba zabezpečení může způsobit, že uzly sítě Sui nebudou schopny zpracovávat nové transakce, což se rovná úplnému vypnutí celé sítě.

Zrovna minulé pondělí CertiK obdržel odměnu 500 000 USD za chybu SUI za odhalení této hlavní bezpečnostní chyby. CoinDesk, autoritativní média v americkém průmyslu, informovala o incidentu a poté hlavní média následovala jeho zprávu a zveřejnila relevantní zprávy.

Této bezpečnostní chybě se živě říká „hamster wheel“: její jedinečná metoda útoku se liší od aktuálně známých útoků. Útočníkovi stačí odeslat datovou část o velikosti asi 100 bajtů, aby spustil nekonečnou smyčku v ověřovacím uzlu Sui reagovat na nové transakce.

Poškození způsobené útokem navíc může přetrvávat i po restartu sítě a může se automaticky šířit v síti Sui, takže všechny uzly jako křeček nekonečně běžící na kole nemohou zpracovávat nové transakce. Proto tomuto jedinečnému typu útoku říkáme útok „kolečka křečka“.

Po zjištění zranitelnosti ji CertiK nahlásil Sui prostřednictvím Suiova bug bounty programu. Sui také co nejdříve účinně zareagoval, potvrdil závažnost zranitelnosti a aktivně přijal odpovídající opatření k nápravě problému před spuštěním mainnetu. Kromě opravy této konkrétní chyby zabezpečení společnost Sui implementovala preventivní opatření ke snížení potenciálních škod, které by tato chyba zabezpečení mohla způsobit.

Aby Sui poděkovala týmu CertiK za zodpovědné zveřejnění, udělila týmu CertiK bonus 500 000 USD.

Následující technické podrobnosti o této kritické zranitelnosti budou zveřejněny, abychom objasnili hlavní příčinu a potenciální dopad této zranitelnosti.

Podrobné vysvětlení zranitelností

Klíčová role validátorů v Sui

U blockchainů založených na jazyce Move, jako jsou Sui a Aptos, je záručním mechanismem k zamezení útoků se škodlivými daty hlavně technologie statického ověřování. Prostřednictvím technologie statického ověřování může Sui zkontrolovat platnost užitečného zatížení předloženého uživateli před uvolněním nebo upgradem smlouvy. Validátor poskytuje řadu kontrolorů pro zajištění správnosti struktury a sémantiky Teprve po absolvování kontrol a ověření vstoupí smlouva k provedení na virtuální stroj Move.

Hrozby škodlivého zatížení v řetězci Move

Řetězec Sui poskytuje novou sadu modelů úložiště a rozhraní nad původním virtuálním počítačem Move, takže Sui má upravenou verzi virtuálního počítače Move. Za účelem podpory nových úložných primitiv Sui dále zavádí řadu dodatečných, přizpůsobených kontrol pro ověření zabezpečení nedůvěryhodných dat, jako je zabezpečení objektů a globální přístup k úložišti. Tyto vlastní kontroly odpovídají jedinečným funkcím společnosti Sui, proto je nazýváme validátory Sui.

Suiho příkaz ke kontrole nákladu

Jak je znázorněno na obrázku výše, většina kontrol ve validátoru provádí ověření zabezpečení na úrovni struktury proti modulu CompiledModule (který představuje běh užitečného zatížení smlouvy poskytnuté uživatelem). Například použijte "Duplicate Checker", abyste zajistili, že v runtime datové části nejsou žádné duplicitní položky, použijte "Limit Checker", abyste zajistili, že délka každého pole v runtime datové části bude v rámci povoleného limitu vstupu.

Kromě kontrol na úrovni struktury vyžaduje statická kontrola ověřovatele stále složitější metody analýzy, aby byla zajištěna robustnost nedůvěryhodného užitečného zatížení na sémantické úrovni.

Další informace o abstraktním interpretu Move:

Lineární a iterativní analýza

Abstraktní interpret poskytovaný Move je rámec speciálně navržený pro provádění komplexní bezpečnostní analýzy bajtového kódu prostřednictvím abstraktní interpretace. Tento mechanismus činí ověřovací proces jemnějším a přesnějším a každý ověřovatel může definovat svůj jedinečný abstraktní stav pro analýzu.

Při spuštění běhu abstraktní interpret sestaví graf řídicího toku (CFG) z kompilovaných modulů. Každý základní blok v těchto CFG udržuje sadu stavů, konkrétně „stav před objednáním“ a „stav po objednávce“. "Stav před objednáním" poskytuje snímek stavu programu před provedením základního bloku, zatímco "stav po objednávce" poskytuje popis stavu programu po provedení základního bloku.

Když abstraktní interpret nenarazí na žádné skoky (nebo smyčky) v grafu toku řízení, řídí se jednoduchým principem lineárního provádění: každý základní blok je postupně analyzován a předchozí instrukce je vypočítána na základě sémantiky každé instrukce v bloku. sekvenční stav a postsekvenční stav. Výsledkem je přesný snímek stavu každého základního bloku na úrovni programu během provádění, což pomáhá ověřit bezpečnostní vlastnosti programu.

Přesunout pracovní postup abstraktního tlumočníka

Tento proces se však stává komplikovanějším, když jsou v řídicím toku smyčky. Výskyt smyčky znamená, že graf řídícího toku obsahuje odrazovou hranu Zdroj odrazové hrany odpovídá následnému stavu aktuálního základního bloku a cílový základní blok (hlava smyčky) odrazové hrany je dříve analyzovaný. Stav předobjednávky základního bloku, takže abstraktní interpret potřebuje pečlivě sloučit stavy dvou základních bloků souvisejících se skokem.

Pokud se zjistí, že se sloučený stav liší od stávajícího stavu předobjednávky základního bloku hlavy smyčky, abstraktní interpret aktualizuje stav základního bloku hlavy smyčky a restartuje analýzu počínaje tímto základním blokem. Tento proces iterativní analýzy pokračuje, dokud není představ smyčky stabilní. Jinými slovy, tento proces se opakuje, dokud se stav předobjednávky základního bloku v čele smyčky mezi iteracemi již nemění. Dosažení pevného bodu znamená, že analýza smyčky je dokončena.

Sui IDLeak validátor:

Přizpůsobená analýza abstraktní interpretace

Na rozdíl od původního návrhu Move zavádí Sui's blockchain platforma jedinečný model globálního úložiště zaměřený na „cíl“. Pozoruhodným rysem tohoto modelu je, že jakákoli datová struktura s klíčovým atributem (uložená jako index v řetězci) musí mít typ ID jako první pole struktury. Pole ID je neměnné a nelze jej přenést na jiné cíle, protože každý objekt musí mít globálně jedinečné ID. Aby byly tyto vlastnosti zajištěny, Sui vybudovala sadu vlastní analytické logiky nad abstraktním interpretem.

Ověřovač IDLeak, také známý jako id_leak_verifier, pracuje ve spojení s abstraktním interpretem při provádění analýzy. Má svou vlastní unikátní AbstractDomain, nazvanou AbstractState. Každý AbstractState se skládá z AbstractValue odpovídající více lokálním proměnným. Monitorujte stav každé místní proměnné pomocí AbstractValue a sledujte, zda je proměnná ID nová.

Během procesu balení struktury umožňuje validátor IDLeak pouze zabalit nové ID do struktury. Prostřednictvím analýzy abstraktní interpretace může validátor IDLeak vyčerpávajícím způsobem sledovat stav místního datového toku, aby zajistil, že žádná existující ID nebudou přenesena do jiných objektů struktury.

Problém s nekonzistencí údržby stavu validátoru Sui IDLeak

Validátor IDLeak je integrován s abstraktním interpretem Move implementací funkce AbstractState::join. Tato funkce hraje nedílnou roli při řízení stavu, zejména při slučování a aktualizaci stavových hodnot.

Prozkoumejte tyto funkce podrobně, abyste pochopili jejich fungování:

V AbstractState::join funkce bere jako vstup jiný AbstractState a pokouší se sloučit jeho místní stav s místním stavem aktuálního objektu. Pro každou lokální proměnnou ve vstupním stavu porovnává hodnotu proměnné s její aktuální hodnotou v lokálním stavu (pokud není nalezena, výchozí je AbstractValue::Other). Pokud se tyto dvě hodnoty nerovnají, nastaví příznak „změněno“ jako základ pro to, zda se výsledek sloučení konečného stavu změnil, a aktualizuje hodnotu lokální proměnné v místním stavu voláním AbstractValue::join.

V AbstractValue::join funkce porovnává svou hodnotu s jinou AbstractValue. Pokud jsou stejné, vrátí hodnotu předanou. Pokud se nerovná, vrátí se AbstractValue::Other.

Tato logika údržby stavu však obsahuje skrytý problém nekonzistence. Přestože AbstractState::join vrátí výsledek označující, že se sloučený stav změnil (JoinResult::Changed) na základě rozdílu mezi starou a novou hodnotou, hodnota sloučeného aktualizovaného stavu může být stále nezměněna.

Tento problém s nekonzistencí je způsoben pořadím operací: určení změněného stavu v AbstractState::join nastane před aktualizací stavu (AbstractValue::join) a toto určení neodráží výsledek aktualizace skutečného stavu.

Kromě toho hraje v AbstractValue::join, AbstractValue::Other rozhodující roli ve výsledku fúze. Pokud je například stará hodnota AbstractValue::Other a nová hodnota je AbstractValue::Fresh, aktualizovaná hodnota stavu je stále AbstractValue::Other, i když se staré a nové hodnoty liší, samotný stav tomu tak není. změnit po aktualizaci.

Příklad: Inkoherence ve spojeních stavů

To zavádí nekonzistenci: výsledek sloučení stavů základního bloku je posouzen jako „změněný“, ale samotná hodnota sloučeného stavu se nezměnila. V procesu abstraktní interpretace a analýzy může mít výskyt takových nesrovnalostí vážné důsledky. Zkontrolujeme chování abstraktního interpretu, když se v grafu toku řízení (CFG) objeví smyčky:

Když dojde ke smyčce, abstraktní interpret použije metodu iterační analýzy ke sloučení stavu cílového základního bloku skoku s aktuálním základním blokem. Pokud se sloučený stav změní, abstraktní interpret bude znovu analyzovat počínaje od cíle skoku.

Pokud však operace sloučení analýzy abstraktní interpretace omylem označí výsledek sloučení stavu jako „změněný“, i když se ve skutečnosti hodnota vnitřní proměnné stavu nezměnila, povede to k nekonečné opětovné analýze a vytvoří nekonečnou smyčku. .

dále využívat nesrovnalosti

Spusťte nekonečnou smyčku ve validátoru Sui IDLeak

Využitím této nekonzistence může útočník sestavit škodlivý řídicí tokový graf, aby přivedl validátor IDLeak do nekonečné smyčky. Tento pečlivě sestavený graf řídicího toku se skládá ze tří základních bloků: BB1 a BB2, BB3. Stojí za zmínku, že jsme záměrně zavedli skokovou hranu z BB3 na BB2, abychom vytvořili smyčku.

Škodlivý stav CFG+ může vést k nekonečné smyčce v rámci validátoru IDLeak.

Proces začíná s BB2, kde je AbstractValue konkrétní lokální proměnné nastavena na ::Other. Po provedení BB2 se proces přenese do BB3, kde je stejná proměnná nastavena na ::Fresh. Na konci BB3 je skoková hrana, která přeskočí na BB2.

V procesu abstraktní interpretace a analýzy tohoto příkladu hraje klíčovou roli výše zmíněná nekonzistence. Když je zpracována odrazová hrana, abstraktní interpret se pokusí spojit stav po objednávce BB3 (proměnná je "::Fresh") se stavem předobjednávky BB2 (proměnná je "::Ostatní"). Funkce AbstractState::join si všimla rozdílu mezi starou a novou hodnotou a nastavila příznak „změnit“, aby indikovala, že BB2 je třeba znovu analyzovat.

Dominantní chování "::Other" v AbstractValue::join však znamená, že po sloučení AbstractValue je skutečná hodnota stavové proměnné BB2 stále "::Other" a výsledek sloučení stavu se nezměnil.

Jakmile tedy tento cyklický proces začne, tj. jak validátor pokračuje v opětovné analýze BB2 a všech jeho následných uzlů základního bloku (v tomto případě BB3), pokračuje neomezeně dlouho. Nekonečná smyčka spotřebovává všechny dostupné cykly CPU, takže není schopna zpracovávat odpovědi na nové transakce a tato situace přetrvává i po restartu validátoru.

Využitím této chyby zabezpečení běží validátorové uzly v nekonečné smyčce jako křeček běžící nekonečně na kole a neschopný zpracovávat nové transakce. Proto tomuto jedinečnému typu útoku říkáme útok „kolečka křečka“.

Útok „křečího kola“ může účinně zastavit validátor Sui, čímž ochromí celou síť Sui.

Poté, co jsme pochopili příčinu a spouštěcí proces zranitelnosti, vytvořili jsme konkrétní příklad pomocí následující simulace Move bytecode a úspěšně spustili zranitelnost v simulaci v reálném prostředí:

Tento příklad ukazuje, jak spustit zranitelnost v reálném prostředí pomocí pečlivě vytvořeného bajtkódu. Konkrétně může útočník spustit nekonečnou smyčku ve validátoru IDLeak pomocí užitečného zatížení jen asi 100 bajtů ke spotřebování všech cyklů CPU uzlu Sui, čímž účinně zabrání zpracování nových transakcí a způsobí odmítnutí služby v síti Sui. .

Přetrvávající poškození útoků „kola křečka“ v síti Sui

Sui's bug bounty program má přísná pravidla pro posuzování úrovní zranitelnosti, především na základě stupně poškození celé sítě. Zranitelnost, která splňuje „kritické“ hodnocení, musí vypnout celou síť a účinně zabránit potvrzení nových transakcí a vyžaduje hard fork k vyřešení problému, pokud zranitelnost může způsobit odmítnutí služby pouze některými síťovými uzly, bude hodnoceny jako „střední riziko“ nanejvýš (střední) nebo „vysoké riziko (vysoké)“.

Zranitelnost „křečího kola“, kterou objevil tým CertiK Skyfall, může vypnout celou síť Sui a vyžaduje oficiální vydání nové verze, aby se to upgradovalo a opravilo. Na základě závažnosti zranitelnosti ji Sui nakonec vyhodnotila jako „kritickou“. Abychom dále porozuměli vážnému dopadu útoku „hamster wheel“, musíme porozumět složité architektuře backendového systému Sui, zejména celému procesu uvolňování nebo upgradu transakcí v řetězci.

Přehled interakcí pro odesílání transakcí v Sui

Zpočátku jsou uživatelské transakce odesílány prostřednictvím front-end RPC a po základním ověření předány back-endové službě. Backendová služba Sui je zodpovědná za další ověřování příchozích transakčních dat. Po úspěšném ověření podpisu uživatele je transakce převedena na transakční certifikát (obsahující informace o transakci a také podpis Sui).

Tyto transakční certifikáty jsou základní součástí provozu sítě Sui a lze je šířit mezi různými ověřovacími uzly v síti. U transakcí vytvoření/upgradu smlouvy ověřovací uzel zavolá validátor Sui, aby zkontroloval a ověřil platnost struktury/sémantiky smlouvy těchto certifikátů, než bude možné je zařadit do řetězce. Právě během této kritické fáze ověřování může být spuštěna a zneužita zranitelnost „nekonečné smyčky“.

Když je zranitelnost spuštěna, způsobí to, že ověřovací proces bude přerušen na neurčito, což účinně omezí schopnost systému zpracovávat nové transakce a způsobí úplné vypnutí sítě. Aby toho nebylo málo, situace přetrvává i po restartu uzlu, což znamená, že tradiční zmírňující opatření zdaleka nestačí. Jakmile je tato zranitelnost spuštěna, dojde k „nepřetržitému poškození“, které zanechá trvalý dopad na celou síť Sui.

Suiovo řešení

Po zpětné vazbě od CertiK Sui okamžitě potvrdil zranitelnost a vydal opravu, která řeší kritickou chybu. Oprava zajišťuje konzistenci mezi změnami stavu a příznaky po změně, čímž eliminuje kritický dopad útoků typu „hamster wheel“.

Aby se odstranila výše uvedená nekonzistence, oprava Sui obsahuje malou, ale kritickou úpravu funkce AbstractState::join. Tato oprava odstraňuje logiku určování výsledku sloučení stavu před provedením AbstractValue::join Místo toho nejprve provede funkci AbstractValue::join pro provedení sloučení stavu a nastaví, zda ke sloučení dojde porovnáním konečného výsledku aktualizace s původním stavem. hodnota (stará_hodnota).

Tímto způsobem bude výsledek slučování stavů konzistentní s výsledkem skutečné aktualizace a během procesu analýzy nedojde k žádné nekonečné smyčce.

Kromě opravy této konkrétní chyby zabezpečení Sui nasadila zmírnění, aby snížila dopad budoucích zranitelností validátoru. Podle Suiho odpovědi v hlášení o chybě se zmírnění týká funkce nazvané Denylist.

"Ověřovatelé však mají konfigurační soubor uzlů, který jim umožňuje dočasně odmítnout určité kategorie transakcí. Tuto konfiguraci lze použít k dočasnému zakázání zpracování vydání a upgradů balíčků. Kvůli této chybě je nutné před podepsáním vydání nebo balíčku spustit Sui." upgradujte TX, zatímco seznam odmítnutí zastaví běh validátoru a zahodí škodlivý TX, dočasné odmítnutí výpisu těchto typů TX je 100% efektivní zmírnění (ačkoli dočasně přeruší službu pro každého, kdo se pokouší uvolnit nebo upgradovat kód).

Mimochodem, tento konfigurační soubor TX deny list už nějakou dobu máme, ale také jsme přidali podobný mechanismus pro certifikáty jako následné zmírnění chyby zabezpečení „nekonečná smyčka validátoru“, kterou jste uvedli dříve. S tímto mechanismem budeme mít při tomto útoku větší flexibilitu: použijeme konfiguraci seznamu odmítnutí certifikátů, aby validátor zapomněl na špatné certifikáty (prolomení nekonečné smyčky), a konfiguraci seznamu odmítnutí TX pro zakázání vydávání/upgradů, čímž se zabrání vytváření nových transakcí se škodlivými útoky. Děkujeme, že jste nás přiměli o tom přemýšlet!

Validátor má omezený počet „ticků“ (na rozdíl od plynu) pro ověření bajtového kódu před podepsáním transakce, pokud všechen bajtový kód vydaný v transakci nelze ověřit tolika tikety, validátor odmítne transakci podepsat, čímž zabrání spouštění v síti. Dříve měření fungovalo pouze pro vybranou sadu komplexních validátorů. Abychom tento problém vyřešili, rozšiřujeme měření na každý validátor, abychom zajistili omezení práce prováděné validátorem během ověřovacího procesu každého zaškrtnutí. Opravili jsme také potenciální chybu nekonečné smyčky ve validátoru úniku ID. "

--Pokyny od vývojářů Sui k opravám chyb

Celkově vzato, Denylist umožňuje validátorům dočasně obcházet exploity ve validátorech a účinně předcházet potenciálním škodám způsobeným některými škodlivými transakcemi tím, že deaktivuje proces vydání nebo upgradu. Když se zmírňující opatření Denylistu projeví, uzly zajistí, že mohou pokračovat v práci tím, že obětují své vlastní funkce smlouvy o publikování/aktualizaci.

Shrnout

V tomto článku sdílíme technické podrobnosti o útoku „hamster wheel“ objeveném týmem CertiK Skyfall a vysvětlujeme, jak tento nový útok využívá klíčové zranitelnosti k úplnému vypnutí sítě Sui. Kromě toho jsme se také blíže podívali na včasnou reakci Sui na vyřešení tohoto kritického problému a sdíleli jsme opravu zranitelnosti a následné metody zmírnění podobných zranitelností.