Velkommen tilbake til Sherlocks Vulnerability Spotlight, hvor vi fremhever en virkningsfull sårbarhet som ble avdekket under en Sherlock-revisjon. Denne uken undersøker vi en feil beregning av sikkerhetsnivå funnet i @plaza_finance-konkurransen av @0xadrii, @KupiaSecurity, @f, @farman1094_ og @0xnovaman33.
Sammendrag av sikkerhetsproblemet: I getRedeemAmount(...) beregner kontrakten sikkerhetsnivået for BOND-innløsninger ved hjelp av post-trade-tilstand: Gjeldende kode (sårbar) sikkerhetNivå = ((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRESISJON) / ((bondSupply - depositAmount) * BOND_TARGET_PRICE); Fordi innløsningsprisingen deretter bruker dette estimerte sikkerhetsnivået til å avgjøre om maksprisen ($100 skal betales), kan en angriper kjøpe BOND til blandede (noen ganger rabatterte) opprettelsesrater til det (nåværende) sikkerhetsnivået faller ≤ 1,2, og deretter løse inn alle BOND til $100-taket – beregner med et utformet depositAmount som skyver det estimerte sikkerhetsnivået tilbake over 1,2. Dette lar angriperen trekke ut ETH ("risikofri" spredning) til poolens nåværende sikkerhetsnivå når terskelen.
Angrepstrinn: 1) Oppsett fase Eksempel på parametere for basseng: - poolReserve = 120 ETH, obligasjonsforsyning = 3000, levSupply = 200, ETH-pris = $3075 Prisregler: Opprett (kjøp) OBLIGASJON: - Hvis sikkerhetNivå ≤ 1,2: creationRate = tvl * 0,8 / obligasjonTilbud - Ellers: creationRate = $100 Løs inn (selg) OBLIGASJON: - Hvis estimert sikkerhetNivå ≤ 1,2: redeemRate = tvl * 0,8 / obligasjonstilbud - Ellers: redeemRate = $100
2) Fase A – Kjøp BOND til blandede/rabatterte priser - Kjøp BOND mens du overvåker (nåværende) sikkerhetNivå = tvl / (obligasjonsforsyning * 100). - Første kjøp skjer mens sikkerhetNivå > 1,2 → preg nær $100 per obligasjon. - Påfølgende kjøp presser nåværende sikkerhetsnivå under 1,2 → mynte til diskontert opprettelsesrate (f.eks. ~$94,07 tommer), og akkumulerer en stor BOND-saldo billig.
3) Fase B – Løs inn alle BOND til maks pris - Ring innløsning(BOND, depositAmount = angriperBondBalance, ...) - Kontrakten beregner estimert sikkerhetsnivå ved å bruke tilstanden etter innløsning (bondSupply - depositAmount) og (tvl - depositAmount * 100) og får (i eksemplet) en verdi > 1,2 - Fordi den estimerte verdien overskrider terskelen, er redeemRate satt til maks $100, slik at angriperen kan ta ut all akkumulert BOND til $100
4) Realisering av fortjeneste - Forskjellen mellom rabatterte kjøp og $100 salg gir netto ETH-fortjeneste. - I PoC-tallene: å bruke 60 ETH over to kjøp gir ~61,89 ETH på innløsning → ~1,89 ETH fortjeneste. - Angriperen kan iterere til det nåværende sikkerhetsnivået for poolen faller til ~1,2, og trekke ut omtrent: uttrekkbare USD ≈ ethPrice × poolReserve − 120 × obligasjonstilbudet
Hva er virkningen? Direkte fondsutvinning / verdilekkasje: Angriperen mynter til rabatterte priser og løser inn til $100, og suger ETH fra poolen. Ubegrenset til terskel: Kan fortsette til poolens gjeldende sikkerhetsnivå krymper til ≈ 1,2. Systemisk prisinkonsekvens: Skaper arbitrasje som ærlige brukere betaler for via dårligere poolreserver/utfall.
Årsaken: Bruk av etterhandelstilstand for prisinnløsninger Koden beregner collateralLevel som om innløsningen allerede har skjedd: bruker (tvl - depositAmount*100) og (bondSupply - depositAmount) sikkerhetNivå = ((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRESISJON) / ((bondSupply - depositAmount) * BOND_TARGET_PRICE); 1. Dette lar en angriper velge depositAmount slik at det estimerte nivået krysser terskelen (> 1.2), og låser opp $100 redeemRate, selv når den gjeldende pool-tilstanden ikke rettferdiggjør det. 2. Terskelporter på en manipulert metrikk Beslutningen om et tak på $100 avhenger av dette manipulerbare estimerte sikkerhetsnivået i stedet for det nåværende (pre-trade) nivået, noe som muliggjør prisspill.
Avbøtende tiltak: Beregn innløsningspriser fra gjeldende utvalgstilstand, ikke de estimerte saldoene etter innløsning. Prosjektets foreslåtte løsning er riktig: - collateralLevel = ((tvl - (depositAmount * BOND_TARGET_PRICE)) * PRESISJON) - / ((bondSupply - depositAmount) * BOND_TARGET_PRICE); + collateralLevel = (tvl * PRECISION) / (obligasjonsforsyning * BOND_TARGET_PRICE);
Ekstra herding (anbefalt): 1. Pris monotonitet: Sørg for at innløsningsprisen ikke øker når depositAmount øker (nei "selg mer, få en bedre enhetspris"). 2. Invariantbasert prising: Utled opprett/løs inn fra en enkelt invariant slik at kjøps-/salgssymmetri forhindrer ensidig arbitrasje. 3. Glidningskontroller: Krev brukeroppgitte min./maks-priser for både oppretting og innløsning. 4. Cap & throttle: Innløsningstak per tx og per blokk for å begrense skade hvis terskler nærmer seg. 5. Konsistens på tvers av baner: Juster oppretting og innløs baner for å bruke samme definisjon av sikkerhetsnivå (bare gjeldende tilstand).
Vi er stolte over å ha bidratt til å sikre @plaza_finance gjennom dette funnet. Når det absolutt må være sikkert, er Sherlock det riktige valget.
3,39K