Mi az a reentrancy támadás?
Reentrancy támadásról akkor beszélünk, amikor egy szerződés egy hívás során átadja a vezérlést egy másik szerződésnek, és a külső kód visszaugrik az első szerződésbe, mielőtt az befejezné az állapotadatok frissítését. Ezzel az időzítési trükkel a támadó újra és újra megismételhet olyan érzékeny műveleteket, mint a pénzfelvétel. Képzeld el, hogy visszatérítést kérsz, majd visszasurransz a pulthoz, mielőtt a pénztáros bezárná a kasszát.
„Csak a régi kódokat érheti reentrancy támadás.” Ez nem igaz. Bármelyik szerződés sebezhető lehet, amely a saját állapotának rögzítése előtt külső hívást indít, ha a logikája hibás.
Hogyan működik a reentrancy támadás?
Egy rövid történet. Egy tipikus okosszerződésnek van egy pénzfelvételi függvénye, amely pénzt küld a hívónak. Ha előbb elküldi a pénzt, és csak utána nullázza az egyenleget, a támadó egy callbackkel visszajuthat a szerződésbe, és újabb összeget kérhet, mielőtt az egyenleg nullára állna.
- Kezdés: A támadó befizet valamennyi pénzt, hogy legitimnek tűnjön.
- Hívás: A támadó meghívja a célként kiszemelt szerződés pénzfelvételi függvényét.
- Visszahívás: A célként kiszemelt szerződés pénzt küld, ezzel lefuttatva a támadó fallback függvényét.
- Ismétlés: A fallback újra meghívja a pénzfelvételi függvényt, mielőtt frissülne az egyenleg.
- Lecsapolás: A ciklus addig folytatódik, amíg a szerződésből el nem fogy a pénz vagy a gas. Igen, ez a trükk.
Egy apró sorrendi hiba, óriási probléma.
Miért fontos a reentrancy támadás?
Azért fontos, mert az időzítési hibák valós pénzeket mozgatnak, méghozzá gyorsan. Ráadásul ez egy olyan klasszikus támadás, amelyet minden fejlesztőnek és kíváncsi felhasználónak azonnal fel kell ismernie.
- Előny: Ha ismered ezt a mintát, könnyebben kiszúrhatod a kockázatos kódot, és biztonságban tarthatod a pénzedet.
- Nézőpont: A nyilvános átláthatóságot használja ki, hiszen minden látható és meghívható egy blokkláncon.
- Jelentőség: Találkozhatsz vele a DeFi-ben, hidaknál, kincstáraknál, sőt a DAO-k irányítási kifizetéseinél is.
A műveletek sorrendje legyen: ellenőrzések, állapotmódosítások, majd interakciók. Először frissítsd az egyenlegeket, és csak utána indíts külső hívásokat. A nagyobb biztonság érdekében használj egyszerű reentrancy védelmet.
A reentrancy támadás fő jellemzői
Íme, mitől működik:
- Rekurzió: A külső kód visszahívja ugyanazt a szerződést, mielőtt az befejeződne.
- Sorrend: A hiba akkor jelentkezik, ha a pénzküldés vagy a külső hívás az állapot frissítése előtt történik.
- Több szerződésen átívelő: A támadás több szerződésen is végighaladhat, nem csak egyetlen függvényen.
- Eszközök: Rosszul megírt kódban ETH-val, tokenekkel, sőt akár nyilvántartott jóváírásokkal is működik.
Változatai
Különböző formák, ugyanaz a fejfájás a hanyagul megírt kódban:
- Egyszeres: Ugyanazon függvény ismételt újrahívása.
- Keresztirányú: Újrahívás egy másik függvényen keresztül, ugyanazon a szerződésen belül.
- Többszörös: Újrahívás két vagy több szerződésen keresztül, ciklusban.
- Csak olvasási: A nézetfüggvények vagy árfolyam-orákulumok befolyásolása, hogy a későbbi írási műveleteket megtévesszék.
A reentrancy támadás kivédése nem csak egyetlen függvényről szól. Vizsgálj felül minden külső hívást, teszteld a szokatlan hívási láncokat, és rendszeresen végezz auditokat.
Példa
A 2016-os The DAO elleni támadás egy reentrancy ciklust használt a pénzfelvételnél, mielőtt az egyenlegeket törölték volna, és percek alatt lecsapolta a hatalmas kincstárat.
Érdekesség
A „checks then effects then interactions” jelmondat a korai biztonsági útmutatókból ered, és azért maradt fenn, mert rövid, könnyű megjegyezni, és működik.
Összefoglalás
A rövid változat, amit érdemes észben tartani: ha a külső kód még a saját nyilvántartásod frissítésének befejezése előtt hívhat meg téged, számíts rá, hogy meg is teszi, és akár ingyen pénzt is adhatsz neki. Ez a reentrancy támadás.