Nomad Bridge incidentanalys

Källnod: 1614638

Tl;dr: Att bygga ett bättre kryptoekosystem innebär att bygga en bättre, mer rättvis framtid för oss alla. Det är därför vi investerar i det större samhället för att se till att alla som vill delta i kryptoekonomin kan göra det på ett säkert sätt. I det här blogginlägget delar vi med oss ​​av lärdomar om sårbarhetens natur, exploateringsmetodik samt analys av angriparens beteende i kedjan under Nomad Bridge-incidenten.

Även om Nomad bridge-kompromissen inte direkt påverkar Coinbase, tror vi starkt på det attacker på alla kryptoföretag är dåliga för branschen som helhet och hoppas att informationen i bloggen kommer att bidra till att stärka och informera liknande projekt om hot och tekniker som används av illvilliga aktörer.

Av: Peter Kacherginsky, Threat Intelligence och Heidi Wilder, Special Investigations

Den 1 augusti 2022 Nomad Bridge drabbades av det fjärde största DeFi-hacket med mer än 186 miljoner dollar stulna på bara några timmar. Som vi har beskrivit i vår senaste blogginlägg, från $540M Ronin Bridge-kompromissen i mars till $250M Wormhole Bridge hack i februari 2022, är det inte en slump att DeFi-broar utgör några av de mest kostsamma incidenterna i vår bransch.

Det som gör Nomad Bridge-kompromissen unik är enkelheten i utnyttjandet och det stora antalet individer som utnyttjar det för att tömma alla lagrade tillgångar bit för bit.

Nomad är ett överbryggande protokoll som stöder Ethereum, Moonbeam och andra kedjor. Nomads bryggprotokoll är byggt med både on-chain och off-chain komponenter. Smarta kontrakt på kedjan används för att samla in och distribuera överbryggade medel medan agenter utanför kedjan vidarebefordrar och verifierar meddelanden mellan olika blockkedjor. Varje blockkedja distribuerar ett replikkontrakt som validerar och lagrar meddelanden i en Merkle-trädstruktur. Meddelanden kan valideras genom att antingen tillhandahålla bevis med provaAndProcess() samtal eller för redan verifierade meddelanden kan de enkelt skickas med bearbeta() ringa upp. Verifierade meddelanden vidarebefordras till en brygghanterare (t.ex. ERC20-router) som kan distribuera överbryggade tillgångar.

Den 21 april 2022 Nomad utplacerade en replika fullmaktsavtal att hantera bearbetning och validering av användares anspråk på överbryggade tillgångar. Denna proxy skulle göra det möjligt för Nomad att enkelt ändra implementeringslogik samtidigt som lagringen behålls över uppgraderingar. Som en del av proxydistributionen ställde Nomad in initiala kontraktsparametrar definierade i utdraget nedan:

funktion initiera(uint32 _remoteDomain,adress _uppdaterare,bytes32 _committedRoot,uint256 _optimisticSeconds) public initializer {__NomadBase_initialize(_updater);// ställ in lagringsvariablerangett = 1;remoteDomain = _remoteDomain;committedRoot = _committedRoot;confirmAt[_committedRoot] = 1;optimisticSeconds = _optimisticSeconds;emit SetOptimisticTimeout(_optimisticSeconds);}

Lägg märke till det markerade bekräftaKl karttilldelning som anger en första post för den betrodda _committedRoot till värdet 1. Variabeln _committedRoot tillhandahålls som en initialiseringsparameter av Nomads kontraktsutvecklare. Låt oss se vad den var inställd på under initieringen:

$ cast run 0x99662dacfb4b963479b159fc43c2b4d048562104fe154a4d0c2519ada72e50bf --quick --rpc-url $MAINNET_RPC_URLSpår:[261514] → ny UpgradeBeaconProxy@"0x5d94…aeba"├─ [2160] UpgradeBeacon::fallback() [staticcall]│   └─ ← 0x0000000000000000000000007f58bb8311db968ab110889f2dfa04ab7e8e831b├─ [163890] Replica::initialize(1635148152, 0xb93d4dbb87b80f0869a5ce0839fb75acdbeb1b77, 0x0000000000000000000000000000000000000000000000000000000000000000, 1800) [delegatcall]│ ├─ emit Ägarskap Överförd(föregåendeÄgare: 0x0000000000000000000000000000000000000000, nyÄgare: 0xa5bd5c661f373256ccfbdbb0│ ├─ emit NewUpdater(oldUpdater: 0x0000000000000000000000000000000000000000, nyUppdaterare: 0xb93d4dbb87b80f0869be5b0839b75b1b77bXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXbXNUMXb│ ├─ emit SetOptimisticTimeout (timeout: 1800)│ └─ ← ()└─ ← 439 byte kod

Intressant nog är initialiseringsparametern _engageradRoot sattes till 0. Som ett resultat av detta bekräftaKl kartan har nu värdet 1 för en 0-post som från april till denna dag:

$ cast call 0x5d94309e5a0090b165fa4181519701637b6daeba "confirmAt(bytes32)" 0x0 --rpc-url $MAINNET_RPC_URL0x0000000000000000000000000000000000000000000000000000000000000001

Den 21 juni 2022 utförde Nomad en serie uppgraderingar av sin överbryggande infrastruktur inklusive Replica-implementeringen. En av ändringarna inkluderade uppdateringar av logiken för meddelandeverifiering i bearbeta() fungera:

funktion process(bytes minne _meddelande) offentliga returnerar (bool _success) {// se till att meddelandet var avsett för den här domänenbytes29 _m = _meddelande.ref(0);require(_m.destination() == localDomain, "!destination");// se till att meddelandet har bevisatsbytes32 _messageHash = _m.keccak();require(acceptableRoot(messages[_messageHash]), "!proven");// kontrollera återinträdesvaktrequire(anged == 1, "!reentrant");angett = 0;// uppdatera meddelandestatus som bearbetatsmeddelanden[_messageHash] = LEGACY_STATUS_PROCESSED;// samtalshanteringsfunktionIMessageRecipient(_m.recipientAddress()).handle(_m.origin(),_m.nonce(),_m.sender(),_m.body().clone());// avger processresultatemit Process(_messageHash, true, "");// återställ återinträdesvaktangett = 1;// returnera santåtervänd sant;}

Meddelandeverifieringsflödet inkluderar nu ett samtal till acceptableRoot() metod som i sin tur refererar bekräftaKl karta vi nämnde ovan:

function acceptableRoot(bytes32 _root) public view returnerar (bool) {// detta är bakåtkompatibilitet för meddelanden som bevisats/bearbetats// under tidigare versionerom (_root == LEGACY_STATUS_PROVEN) returnerar true;om (_root == LEGACY_STATUS_PROCESSED) returnerar false;uint256 _time = confirmAt[_root];if (_tid == 0) {return false;}returnera block.timestamp >= _time;}

Sårbarheten visas i ett scenario när bedrägliga meddelanden, inte finns i den betrodda meddelanden[] karta, skickas direkt till bearbeta() metod. I detta scenario meddelanden[_messageHash] returnerar ett standardvärde null för icke-existerande poster så att acceptableRoot() metoden kallas enligt följande:

require(acceptableRoot(0), "!proven");

I sin tur, acceptableRoot() metod kommer att utföra en uppslagning mot bekräfta Vid[] map med ett nollvärde enligt följande:

uint256 _time = confirmAt[0];if (_tid == 0) {return false;}returnera block.timestamp >= _time;

Som vi nämnde i början av detta avsnitt, bekräfta Vid[] kartan har en nollpost definierad vilket resulterar i acceptableRoot() tillbaka Sant och tillåta bedrägliga meddelanden.

Exploateringen drar fördel av ovanstående sårbarhet genom att skapa ett meddelande som lurar Nomad bridge att skicka lagrade tokens utan korrekt auktorisation. Nedan är ett exempel bearbeta() nyttolast i en transaktion insänd av 0xb5c5…590e:

0x6265616d000000000000000000000000d3dfd3ede74e0dcebc1aa685e151332857efce2d000013d60065746800000000000000000000000088a69b4e698a4b090df6cf5bd7b2d47325ad30a3006574680000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c59903000000000000000000000000b5c55f76f90cc528b2609109ca14d8d84593590e00000000000000000000000000000000000000000000000000000002540be400e6e85ded018819209cfb948d074cb65de145734b5b0852e4a5db25cac2b8c39a

Replikmeddelandet har följande struktur:

struct Message {uint32 _originDomain,bytes32 _sender,uint32 _nonce,uint32 _destinationDomain,bytes32 _mottagare,bytes minne _messageBody}

Mottagaren specifik _messageBody innehåller transaktionsdata som ska behandlas av _mottagare. Nomadmottagare accepterar flera transaktions- och meddelandetyper, men vi kommer att fokusera på överföringstypen:

struct BridgeMessage {uint32-domän;bytes32 id;uint8 typ;bytes32-mottagare;uint256 belopp;uint256 detaljerHash;}

Avkodning av ovanstående nyttolast illustrerar hur 0xb5c55f76f90cc528b2609109ca14d8d84593590e kunde stjäla 100 WBTC genom att skicka in en specialgjord nyttolast för att kringgå Nomads meddelandekontroller.

För att bättre förstå grundorsaken till exploateringen vi utvecklat en PoC för att visa att det dränerar hela tokens saldo på bryggan med bara några få transaktioner:

När vi skrev en PoC fann vi det konstigt att angripare valde att extrahera pengar i mindre steg när de kunde ha dränerat hela beloppet i en enda transaktion. Detta beror sannolikt på att angriparna inte skapar bryggmeddelanden från början, utan istället spelar om befintliga transaktioner med patchade mottagningsadresser.

Över 186 miljoner USD i ERC-20-tokens stals från Nomad Bridge mellan 1 augusti 2022 klockan 21:32 UTC och 2 augusti 2022 klockan 05:49 UTC. Den högsta volymen av stulna tokens var främst USDC, följt av WETH, WBTC och CQT. Inom den första timmen efter exploateringen stals endast WBTC och WETH, sedan följt av flera andra ERC-20:or.

Källa: Dune Dashboard

När vi analyserar blockchain-data ser vi att det fanns olika adresser som piggybackade från de ursprungliga exploatörerna och använde nästan identisk indata med modifierade mottagaradresser för att ta bort samma token för samma summa. När WBTC-kontraktet till största delen var tömt fortsatte angriparna sedan med att tömma WETH-kontraktet och så vidare.

Ytterligare analysera de första angriparna i blocket 15259101, finner vi att de två första angriparadresserna utnyttjade ett hjälparkontrakt för att fördunkla den exakta exploateringen. Tyvärr, inom samma block, verkar flera index ner en annan exploatörsadress ha kämpat med att interagera med hjälparkontraktet och beslutat att kringgå det - och offentligt avslöja exploateringsindata under processen. Andra adresser i samma och senare block följde sedan efter och använde nästan identiska nyttolaster för att utföra exploateringen.

Efter den första exploateringen, och på grund av hur lätt det var att utlösa exploateringen, anslöt sig hundratals copycats till en massiv exploatering av ett enda kontrakt. När vi analyserade nyttolasten för olika framtida angripare fann vi att det inte bara fanns återanvändning av samma tokens som överbryggades och samma mängder, utan också att medel konsekvent "överbryggades" från Moonbeam precis som den ursprungliga exploateringen.

Attacken skedde i tre steg: sårbarhetstestningen en dag före attacken, den initiala exploateringen riktad mot WBTC lagrad på bryggan och copycat-steget som involverade hundratals unika adresser. Låt oss dyka in i var och en av dessa inklusive delvis återlämnande av stulna tillgångar.

Under hela den 31 juli 2022, bitliq[.]eth visade sig utlösa sårbarheten med hjälp av små mängder WBTC och andra tokens. Till exempel, den 31 juli–2022 kl. 11:19:39 +UTC skickade han ett transaktion till bearbeta() metod på Ethereum blockchain med följande nyttolast:

0x617661780000000000000000000000005e5ea959686c73ed32c1bc71892f7f317d13a267000000390065746800000000000000000000000088a69b4e698a4b090df6cf5bd7b2d47325ad30a36176617800000000000000000000000050b7545627a5162f82a992c33b87adc75187b21803000000000000000000000000a8c83b1b30291a3a1a118058b5445cc83041cd9d000000000000000000000000000000000000000000000000000000000000f6088a36a47f8e81af64c44b079c42742190bbb402efb94e91c9515388af4c0669eb

Nyttolasten kan avkodas enligt följande:

  • Ursprungskedja: "avax"
  • Destinationskedja: "eth"
  • Recipient: a8c83b1b30291a3a1a118058b5445cc83041cd9d (bitliq[.]eth)
  • Token-adress: 0x50b7545627a5162F82A992c33b87aDc75187B218 (WBTC.e om Avalanche)
  • Belopp: 0.00062984 BTC

Detta motsvarar 0.00062984 BTC transaktion skickas till bron på Avalanchekedjan.

Nyttolasten skickades med hjälp av bearbeta() metod i motsats till den vanligare provaAndProcess() och var inte närvarande i meddelandet[]-kartan före exekveringen i block 15249928:

$ cast call 0x5d94309e5a0090b165fa4181519701637b6daeba "messages(bytes32)" "bc0f99a3ac1593c73dbbfe9e8dd29c749d8e1791cbe7f3e13d9ffd3ddea57284" --rpc-url $MAINNET_RPC_URL --block 152499280x0000000000000000000000000000000000000000000000000000000000000000

Transaktionen lyckades även utan att tillhandahålla nödvändiga bevis genom att utlösa sårbarheten i acceptableRoot() metod genom att förse den med ett 0x0 root-hashvärde som illustreras i felsökaren nedan:

Källa: Tenderly Debugger

Meddelanden som inte finns i meddelanden[] lagring kan valideras med hjälp av provaAndProcess() metod; dock eftersom adressen ringde bearbeta() direkt har de utlöst sårbarheten.

Intressant nog verkar det som att bitliq[.]eth sannolikt också testade ERC-20-bryggkontraktet en timme före exploateringen och bryggde över 0.01 WBTC till Moonbeam. [Tx]

Aktivt utnyttjande startade den 1 augusti 2022, allt inom samma block 15259101 och resulterade i en kombinerad stöld av 400 BTC.

Alla fyra transaktionerna använde identiska nyttolaster med undantag för en mottagaradress som beskrivs i Sårbarhet avsnitt ovan:

0x6265616d000000000000000000000000d3dfd3ede74e0dcebc1aa685e151332857efce2d000013d60065746800000000000000000000000088a69b4e698a4b090df6cf5bd7b2d47325ad30a3006574680000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c59903000000000000000000000000f57113d8f6ff35747737f026fe0b37d4d7f4277700000000000000000000000000000000000000000000000000000002540be400e6e85ded018819209cfb948d074cb65de145734b5b0852e4a5db25cac2b8c39a

Några iakttagelser om ovanstående:

  • De tre första adresserna finansierades av Tornado Cash och har aktivt gjort transaktioner med varandra, vilket indikerar en enskild aktörsgrupp.
  • Till skillnad från de två första exploateringstransaktionerna, 0xb5c5…590e och bitliq[.]eth skickade nyttolasten direkt till kontraktet och utan användning av flashbots för att dölja den från offentliga mempool.
  • bitliq[.]eth spelade upp en tidigare exploateringstransaktion i samma block 15259101 som 0xb5c5…590e anger antingen förkunskaper om utnyttjandet eller lärande om 0xb1fe…ae28 från mempoolen.
  • Alla fyra transaktionerna använde identiska nyttolaster, var och en stjäl 100 WBTC åt gången.

Totalt identifierades 88 % av adresserna som utförde bedrifterna som copycats och tillsammans stal de omkring 88 miljoner dollar i tokens från bron.

Majoriteten av copycats använde en variant av den ursprungliga exploateringen genom att helt enkelt ändra riktade tokens, belopp och mottagaradresser. Vi kan klassificera unika nyttolaster genom att gruppera dem baserat på kontrakt som de anropar och unik metod 4byte anropad enligt illustrationen nedan:

Baserat på vår analys kallade mer än 88 % av unika adresser det sårbara kontraktet direkt med hjälp av 928bc4b2 funktionsidentifierare som motsvarar process(bytes) metod som användes i den ursprungliga exploateringen. Resten utför samma samtal med hjälp av mellanhandskontrakt som t.ex 1cff79cd vilken är exekvera (adress, byte) metod, batchning av flera bearbeta() transaktioner tillsammans och andra mindre variationer.

Efter den första kompromissen var de ursprungliga exploatörerna tvungna att tävla mot hundratals copycats:

Medan majoriteten av värdefulla tokens gjorde anspråk på bara två av de ursprungliga exploatörernas adresser, kunde hundratals andra göra anspråk på en del av bridges innehav:

Nedan är ett diagram som visar tokens stulna över tiden i USD. Det blir uppenbart att exploatörerna gick ton för token när de dränerade bron.

Hittills har 12 % som stulits från Nomad Bridge-kontraktet återlämnats — inklusive partiella returer. Majoriteten av returerna skedde timmarna efter Nomad Bridges begäran om att skicka pengar till återvinningsadressen den 3 augusti 2022. [Tweeta, Tx]

Nedan är en uppdelning av de återlämnade medlen, som inkluderar ETH och olika andra tokens, av vilka några aldrig ens var på bron:

Pengar fortsätter att skickas tillbaka till brons återställningsadress, om än långsammare under de senaste dagarna än när adressen ursprungligen publicerades:

Majoriteten av returnerade medel verkar vara i USDC, följt av DAI, CQT, WETH och WBTC. Detta skiljer sig markant från fördelningen av de utnyttjade tokens. Anledningen var att de ursprungliga exploatörerna i första hand dränerade bron mellan WBTC och WETH. Till skillnad från exploatörer i senare skede, flyttade dessa exploatörer runt pengar utan avsikt att lämna tillbaka dem.

Intressant nog har en av de ursprungliga exploatörerna, bitliq[.]eth, endast returnerat 100 ETH till bryggkontraktet, men har börjat ta ut resten av sina intäkter genom renBTC och bränna det i utbyte mot BTC.

Kategorisering av "utnyttjare"

Vid bedömningen av Nomad Bridge-exploatörerna kategoriserades angriparna i följande hinkar:

  • Svarta hattar: De som inte ger tillbaka pengar och fortsätter att flytta dem vidare.
  • Vita hattar: De som helt och hållet skickar pengar tillbaka till återställningsadresserna
  • Observera att även om vi använder termen vit hatt i förklaringssyfte här, godkändes inte den första insamlingen av pengarna och är inte en aktivitet som vi skulle stödja.
  • Grå hattar: De som delvis skickar pengar tillbaka till återvinningsadresserna.
  • Okända okända: De som ännu inte har flyttat pengar.

Cirka 24 % av medlen fortsätter att stå orörda. Vi misstänker att dessa antingen är angripare som väntar på värmen eller listiga degener som håller ut för en belöning från Nomad. Den största volymen medel har dock gått framåt. Från och med den 5 augusti uppskattar vi att ~64% har gått framåt.

För att hålla dig uppdaterad med det senaste när det gäller de pengar som returneras, kolla in denna instrumentpanel.

Fördjupa sig i Blackhats

Av de fonder som har gått vidare har vi identifierat flera stora ringar av adresser som alla kombinerar fonder. I synnerhet verkar ett kluster av adresser ha samlat på sig över $62 miljoner i volym. Intressant nog var en adress inom detta kluster den första adressen som utförde exploateringen [tx hash].

Hittills ser vi i första hand dessa ringar efter ett av nedanstående mönster:

  • MEV-botaktivitet
  • Blanda och håll kvar för att vänta ut värmen
  • Byta pengar och så småningom returnera en del av pengarna till återvinningsadressen
  • Byta medel och investera DeFi-projekt eller ta ut pengar på olika CEX
  • Flytta pengar genom Tornado Cash

Nedan är ett exempel på hur vissa adresser har börjat flytta pengar genom Tornado Cash, som den 8 augusti 2022 är en sanktionerad enhet.

Akta dig för bedrägerier:

Flera vita hattar har redan lämnat tillbaka över 10 % av medlen till brokontraktet. Detta var dock inte utan hicka.

Ursprungligen skrev Nomad-teamet på båda Twitter och om blockchain Ethereum-adressen att skicka eventuella utnyttjade medel till

Men bedragare följde efter och satte upp olika bedrägliga ENS-domäner för att posera som Nomad-teamet och bad att de skulle få pengar skickade till fåfänga adresser med samma initiala tecken som den legitima återställningsadressen.

Till exempel nedan är ett meddelande skickat av en av bedragarna. Notera den bedrägliga återställningsadressen, ENS-domänen och även 10%-premien. Nomad har sedan dess erbjudit att vita hattar kräver 10% av utnyttjade intäkter. [Tx]

Även om de flesta kontrakt granskas omfattande av olika blockchain-revisorer, kan kontrakt fortfarande innehålla sårbarheter som ännu inte har upptäckts. Även om du kanske vill ge likviditet till ett visst protokoll eller överbrygga medel, är här några tips att tänka på:

  • När du tillför likviditet, håll inte alla dina pengar på ett protokoll eller lagrade i bryggan.
  • Se till att regelbundet granska och återkalla alla kontraktsgodkännanden du inte aktivt behöver.
  • Håll dig uppdaterad med säkerhetsinformationsflöden för att spåra protokoll du har investerat i.

Coinbase har åtagit sig att förbättra vår säkerhet och den bredare branschens säkerhet, samt att skydda våra användare. Vi tror att sådana här utnyttjande kan mildras och i slutändan förhindras. Förutom att göra kodbaser med öppen källkod för allmänheten att granska, rekommenderar vi frekventa protokollrevisioner, implementera bug-bounty-program och aktivt arbeta med säkerhetsforskare. Även om denna exploatering var en svår inlärningsupplevelse, tror vi att förståelsen av hur exploateringen inträffade bara kan hjälpa vår unga bransch att utvecklas ytterligare.

Tidsstämpel:

Mer från Coinbasen