NewsDevelopersEnterpriseBlockchain ExplainedEvents and ConferencesPressHírlevelek
Contents
- 1 Ethereum intelligens szerződés biztonsági ajánlások
- 1.0.0.1 Külső hívások
- 1.0.0.1.1 Vigyázzon, ha külső hívásokat indít
- 1.0.0.1.2 Megbízhatatlan szerződések megjelölése
- 1.0.0.1.3 Kerülje az állapotváltozásokat külső hívások után
- 1.0.0.1.4 Ne használja a transfer () vagy a send ().
- 1.0.0.1.5 Kezelje a külső hívások hibáit
- 1.0.0.1.6 Kedvező húzás a külső hívásokhoz
- 1.0.0.1.7 Ne hívjon megbízhatatlan kódot
- 1.0.0.1.8 Figyelem
- 1.0.0.2 Ne feledje, hogy az éter erőszakkal elküldhető egy számlára
- 1.0.0.3 Ne feledje, hogy az on-chain adatok nyilvánosak
- 1.0.0.4 Vigyázzon azzal a lehetőséggel, hogy egyes résztvevők „offline állapotba kerülhetnek” és nem térnek vissza
- 1.0.0.5 Biztonságos a blokklánc-kódod?
- 1.0.0.1 Külső hívások
- 1.0.1 Hogyan készítsünk sikeres blokklánc terméket
- 1.0.2 Hogyan állítsunk be és futtassunk Ethereum csomópontot
- 1.0.3 Hogyan készítsünk saját Ethereum API-t
- 1.0.4 Hogyan hozzunk létre közösségi tokent
- 1.0.5 Biztonsági eszközök használata az intelligens szerződés-fejlesztésben
- 1.0.6 A pénzügyek jövője: digitális eszközök és DeFi
Iratkozzon fel hírlevelünkre.
Email cím
Tiszteletben tartjuk a magánéletét
HomeBlogBlockchain fejlesztés
Ethereum intelligens szerződés biztonsági ajánlások
A külső hívások kezelésétől kezdve az elkötelezettségi rendszerekig itt találunk 10+ intelligens szerződéses biztonsági mintát, amelyeket az Ethereumra építve kell követni. – ConsenSys, 2020. július 10., 2020. július 10.
Amint azt az intelligens szerződéses biztonsági gondolkodásmódban bemutattuk, az éber Ethereum fejlesztő mindig öt alapelvet tart szem előtt:
- Készüljön fel a kudarcra
- Óvatosan indítsa el
- Tartsa egyszerűnek a szerződéseket
- Maradj naprakész
- Legyen tisztában az EVM sajátosságaival
Ebben a bejegyzésben elmélyülünk az EVM sajátosságaiban, és végigvezetünk egy listát azokról a mintákról, amelyeket be kell tartanod, ha bármilyen intelligens szerződéses rendszert fejlesztesz az Ethereumon. Ez a darab elsősorban az Ethereum középhaladóinak szól. Ha még mindig a feltárás korai szakaszában jár, nézze meg a ConsenSys Academy igény szerinti blockchain fejlesztői programját.
Oké, merüljünk be.
Külső hívások
Vigyázzon, ha külső hívásokat indít
A nem megbízható intelligens szerződésekre történő felhívás számos váratlan kockázatot vagy hibát okozhat. A külső hívások rosszindulatú kódokat hajthatnak végre az adott szerződésben vagy bármely más szerződésben, amely attól függ. Ezért kezeljen minden külső hívást potenciális biztonsági kockázatként. Ha nem lehetséges, vagy nem kívánatos a külső hívások eltávolítása, használja a szakasz további részében található ajánlásokat a veszély minimalizálása érdekében.
Megbízhatatlan szerződések megjelölése
Külső szerződésekkel való interakció során nevezze meg a változókat, módszereket és szerződéses interfészeket úgy, hogy világossá váljon, hogy a velük való interakció potenciálisan nem biztonságos. Ez vonatkozik a saját funkcióira, amelyek külső szerződéseket hívnak.
// rossz Bank.withdraw (100); // Nem világos, hogy a makeWithdrawal (uint amount) megbízható vagy nem megbízható függvény-e {// Nem világos, hogy ez a függvény potenciálisan nem biztonságos. Bank.withdraw (összeg); } // jó UntrustedBank.withdraw (100); // nem megbízható külső hívás TrustedBank.withdraw (100); // külső, de megbízható banki szerződés, amelyet az XYZ Corp függvény karbantart a makeUntrustedWithdrawal (uint összeg) {UntrustedBank.withdraw (összeg); } Kód nyelve: PHP (php)
Kerülje az állapotváltozásokat külső hívások után
Függetlenül attól, hogy nyers hívásokat (a someAddress.call () formában) vagy szerződéses hívásokat (az ExternalContract.someMethod () formában) használ, tegyük fel, hogy rosszindulatú kód futtatható. Még akkor is, ha az ExternalContract nem rosszindulatú, a rosszindulatú kód futtatható bármely általa meghívott szerződéssel.
Az egyik különös veszély, hogy a rosszindulatú kód eltérítheti a vezérlési folyamatot, ami az újbóli belépés miatt sebezhetőséghez vezet. (Lát Visszatérés a probléma teljesebb megvitatásához).
Ha nem megbízható külső szerződésre hív, kerülje az állapotváltozásokat a hívás után. Ezt a mintát néha a ellenőrzések-hatások-interakciók mintája.
Lát SWC-107
Ne használja a transfer () vagy a send ().
.továbbítsa () és.küldje () pontosan 2300 gázt továbbítson a címzettnek. Ennek a keménykódolt gázdíjnak a célja a megelőzés volt reentrancia sebezhetőségei, de ennek csak abban a feltételezésben van értelme, hogy a gázköltségek állandóak. EIP 1884, amely az isztambuli keményvilla része volt, megemelte a SLOAD művelet gázköltségét. Ez azt okozta, hogy a szerződés tartalék funkciója több mint 2300 gázba került. Javasoljuk, hogy hagyja abba a.transfer () és.send () használatát, ehelyett használja a.call ().
// rossz szerződés Vulnerable {function cancel (uint256 összeg) external {// Ez 2300 gázt továbbít, ami nem biztos, hogy elég, ha a címzett // szerződés és a gázköltségek változnak. msg.sender.transfer (összeg); }} // jó szerződés Fix {függvény visszavonás (uint256 összeg) külső {// Ez továbbítja az összes rendelkezésre álló gázt. Feltétlenül ellenőrizze a visszatérési értéket! (bool siker,) = msg.sender.call.value (összeg) (""); megkövetelik (siker, "Az átvitel nem sikerült."); }} Kód nyelve: JavaScript (javascript)
Ne feledje, hogy a. Call () nem tesz semmit az újbóli belépési támadások enyhítésére, ezért más óvintézkedéseket kell tenni. A visszatérési támadások megelőzéséhez használja a ellenőrzések-hatások-interakciók mintája.
Kezelje a külső hívások hibáit
A Solidity alacsony szintű hívási módszereket kínál, amelyek a nyers címeken működnek: address.call (), address.callcode (), address.delegatecall () és address.send (). Ezek az alacsony szintű módszerek soha nem vetnek ki kivételt, de hamis értéket adnak vissza, ha a hívás kivétellel találkozik. Másrészt a szerződéses hívások (pl. ExternalContract.doSomething ()) automatikusan továbbítják a dobást (például az ExternalContract.doSomething () akkor is dob, ha a doSomething () dobja).
Ha alacsony szintű hívási módszerek mellett dönt, győződjön meg arról, hogy a visszahívási érték ellenőrzésével kezeli a hívás sikertelenségének lehetőségét..
// rossz néhányAddress.send (55); someAddress.call.value (55) (""); // ez kétszeresen veszélyes, mivel továbbítja az összes megmaradt gázt, és nem ellenőrzi az eredményt someAddress.call.value (100) (bytes4 (sha3 ("letét()"))); // ha a betét kivételt vet, a nyers hívás () csak hamis értéket ad vissza, és a tranzakció NEM kerül visszaállításra // jó (bool siker,) = someAddress.call.value (55) (""); if (! siker) {// hibakód kezelése} ExternalContract (someAddress) .deposit.value (100) (); Kód nyelve: JavaScript (javascript)
Lát SWC-104
Kedvező húzás a külső hívásokhoz
A külső hívások véletlenül vagy szándékosan kudarcot vallhatnak. Az ilyen hibák okozta kár minimalizálása érdekében gyakran jobb, ha minden külső hívást elkülönítünk a saját tranzakciójukból, amelyet a hívás fogadója kezdeményezhet. Ez különösen releváns a fizetéseknél, ahol jobb, ha hagyjuk, hogy a felhasználók pénzfelvételt végezzenek, ahelyett, hogy automatikusan pénzhez juttatnák őket. (Ez is csökkenti az esélyét problémák a gáz határértékével.) Kerülje a több étertranszfer kombinálását egyetlen tranzakcióban.
// rossz szerződés aukciója {address higherBidder; uint maximumBid; függvény ajánlat () fizetendő {igényel (msg.value >= legmagasabbBid); if (legnagyobbBidder! = cím (0)) {(bool siker,) = legnagyobbBidder.call.value (legnagyobbBid) (""); megkövetelik (siker); // ha ez a hívás folyamatosan kudarcot vall, senki más nem tud licitálni} maximumBidder = msg.sender; maximumBid = msg.value; }} // jó szerződéses aukció {address maximumBidder; uint maximumBid; leképezés (cím => uint) visszatérítések; függvény ajánlat () fizetendő külső {igényel (msg.value >= legmagasabbBid); if (legmagasabb ajánlattevő! = cím (0)) {visszatéríti [legmagasabb ajánlatot] + = legmagasabb licit; // rögzítsük a visszatérítést, amelyet ez a felhasználó igényelhet} maximumBidder = msg.sender; maximumBid = msg.value; } függvény visszavonása (visszatérítés) visszatérítés () külső {uint visszatérítés = visszatérítés [msg.sender]; visszatérítések [msg.sender] = 0; (bool siker,) = msg.sender.call.value (visszatérítés) (""); megkövetelik (siker); }} Kód nyelve: JavaScript (javascript)
Lát SWC-128
Ne hívjon megbízhatatlan kódot
A delegatecall függvény más szerződésekből hívja a függvényeket, mintha a hívó szerződéshez tartoznának. Így a megbízott megváltoztathatja a hívó cím állapotát. Ez bizonytalan lehet. Az alábbi példa megmutatja, hogy a delegatall hívás felhasználása a szerződés megsemmisüléséhez és egyensúlyának elvesztéséhez vezethet.
contract Destructor {function doWork () external {selfdestruct (0); }} szerződéses munkavállaló {function doWork (_internalWorker cím) public {// nem biztonságos _internalWorker.delegatecall (bytes4 (keccak256 ("dolgozni()"))); }} Kód nyelve: JavaScript (javascript)
Ha a Worker.doWork () meghívást kap a telepített Destructor szerződés címével argumentumként, akkor a Worker szerződés önpusztít. – Csak megbízható szerződésekre ruházhatja a végrehajtást, és – soha ne a felhasználó által megadott címre.
Figyelem
Ne feltételezzük, hogy a szerződések nulla egyenleggel jönnek létre. A támadó étert küldhet a szerződés címére, mielőtt létrejön. A szerződések nem feltételezhetik, hogy kezdeti állapota nulla egyenleget tartalmaz. Lát 61. szám további részletekért.
Lát SWC-112
Ne feledje, hogy az éter erőszakkal elküldhető egy számlára
Vigyázzon egy olyan invariáns kódolására, amely szigorúan ellenőrzi a szerződés egyensúlyát.
A támadó erőszakkal küldhet étert bármely fiókra. Ezt nem lehet megakadályozni (még egy visszaállítást () végrehajtó tartalék funkcióval sem).
A támadó ezt megteheti úgy, hogy létrehoz egy szerződést, finanszírozza azt 1 wei-vel és meghívja az önmegsemmisítést (áldozatcím). Nincs kód meghívva az áldozatAddressben, ezért nem akadályozható meg. Ez igaz a blokk jutalomra is, amelyet a bányász címére küldenek, amely bármilyen tetszőleges cím lehet.
Továbbá, mivel a szerződés címei előre kiszámíthatók, az étert el lehet küldeni egy címre a szerződés telepítése előtt.
Lát SWC-132
Ne feledje, hogy az on-chain adatok nyilvánosak
Sok alkalmazás megköveteli, hogy a benyújtott adatok bizonyos idõpontig privátak legyenek a mûködéshez. Játékok (pl. Láncos kőzetpapír olló) és aukciós mechanizmusok (pl. Zárt licit Vickrey aukciók) a példák két fő kategóriája. Ha olyan alkalmazást épít, ahol az adatvédelem kérdés, ügyeljen arra, hogy ne követelje a felhasználókat az információk túl korai közzétételéről. A legjobb stratégia a használata kötelezettségvállalási rendszerek külön fázisokkal: először kösse be az értékek kivonatát, majd egy későbbi szakaszban fedje fel az értékeket.
Példák:
- A kőzetpapír ollókban mindkét játékostól előbb követelje meg a tervezett mozdulat kivonatát, majd mindkét játékostól a mozdulat beküldését; ha a beküldött lépés nem felel meg a hashnak, dobja ki.
- Egy aukción megkövetelheti a játékosoktól, hogy az első fázisban adják meg az ajánlati értékük kivonatát (az ajánlati értéküknél nagyobb befizetéssel együtt), majd a második szakaszban nyújtsák be aukciós ajánlatuk értékét..
- Egy véletlenszám-generátortól függő alkalmazás kifejlesztésekor a sorrendnek mindig (1) a játékosoknak kell beküldeniük a mozdulatokat, (2) véletlenszerűen generált számokra, (3) a játékosoknak fizetniük kell. Sokan aktívan kutatják a véletlenszám-generátorokat; A kategória jelenlegi legjobb megoldásai közé tartoznak a Bitcoin blokkfejlécek (a következővel ellenőrizve: http://btcrelay.org), a kivonat-elkötelezettség-felfedés sémák (azaz az egyik fél generál egy számot, közzéteszi hashját, hogy “elkötelezze magát” az érték mellett, majd később feltárja az értéket), és RANDAO. Mivel az Ethereum egy determinisztikus protokoll, a protokollon belül egyetlen változót sem használhat kiszámíthatatlan véletlenszámként. Ne feledje, hogy a bányászok bizonyos mértékben ellenőrzik a block.blockhash () értéket*.
Vigyázzon azzal a lehetőséggel, hogy egyes résztvevők „offline állapotba kerülhetnek” és nem térnek vissza
Ne tegye függővé a visszatérítési vagy igénylési folyamatokat attól, hogy egy adott fél egy adott műveletet hajtson végre, anélkül, hogy más módon kimenne az alapokat. Például egy kő-papír-olló játékban az egyik gyakori hiba az, hogy addig nem fizetnek ki, amíg mindkét játékos el nem adja a mozdulatait; egy rosszindulatú játékos azonban úgy “gyászolhatja” a másikat, hogy soha nem nyújtja be a mozdulatát – sőt, ha egy játékos látja a másik játékos feltárt mozdulatát, és megállapítja, hogy elvesztette, akkor egyáltalán nincs oka a saját lépésének benyújtására. Ez a kérdés az állami csatornarendezéssel összefüggésben is felmerülhet. Ha az ilyen helyzetek problémát jelentenek, (1) lehetőséget nyújt a nem részt vevő résztvevők kijátszására, esetleg határidőn keresztül, és (2) fontolja meg egy további gazdasági ösztönző hozzáadását a résztvevők számára, hogy információkat nyújtsanak be minden olyan helyzetben, amelyben vannak. állítólag.
Óvakodjon a negatívabb előjelű egész szám tagadásától
A szilárdság számos típust biztosít aláírt egész számokkal való együttműködéshez. A legtöbb programozási nyelvhez hasonlóan a Solidityben is egy N bitű előjelű egész szám -2 ^ (N-1) és 2 ^ (N-1) -1 értékeket jelenthet. Ez azt jelenti, hogy nincs pozitív megfelelője a MIN_INT-nek. A tagadás úgy valósul meg, hogy megtalálja a szám kettőjének kiegészítését, tehát a legnegatívabb szám tagadását ugyanannyit eredményez. Ez a Solidity összes aláírt egész típusú típusára igaz (int8, int16,…, int256).
szerződés Negáció {function negate8 (int8 _i) public pure hozamok (int8) {return -_i; } function negate16 (int16 _i) public pure hozamok (int16) {return -_i; } int8 public a = negate8 (-128); // -128 int16 public b = negate16 (-128); // 128 int16 public c = negate16 (-32768); // -32768} Kód nyelve: PHP (php)
Ennek egyik módja, ha ellenőrizzük a változó értékét a tagadás előtt, és dobjuk, ha az megegyezik a MIN_INT értékkel. Egy másik lehetőség annak biztosítása, hogy a legnagyobb negatív számot soha ne érjük el nagyobb kapacitású típus használatával (pl. Int32 helyett int16).
Hasonló probléma az int típusokkal akkor fordul elő, ha a MIN_INT-et megszorozzuk vagy elosztjuk -1-gyel.
Biztonságos a blokklánc-kódod?
Reméljük, hogy ezek az ajánlások hasznosak voltak. Ha Ön és csapata készül az indításra, vagy akár a fejlesztés életciklusának kezdetén van szükségünk, és intelligens szerződéseket kell ellenőrizni, kérjük, forduljon bizalommal a ConsenSys Diligence biztonsági mérnökeinkhez. Segítünk Önnek Ethereum alkalmazásainak 100% -os bizalommal történő elindításában és karbantartásában.
Foglaljon biztonsági ellenőrzést
Foglaljon egy napos áttekintést a blockchain biztonsági szakértőink csapatától. Foglaljon ma Önöknek SecuritySmart szerződésekHírlevélFeliratkozás hírlevelünkre a legfrissebb Ethereum hírekről, vállalati megoldásokról, fejlesztői erőforrásokról és egyebekről. E-mail címExkluzív tartalomWebinárium
Hogyan készítsünk sikeres blokklánc terméket
Webinárium
Hogyan állítsunk be és futtassunk Ethereum csomópontot
Webinárium
Hogyan készítsünk saját Ethereum API-t
Webinárium
Hogyan hozzunk létre közösségi tokent
Webinárium
Biztonsági eszközök használata az intelligens szerződés-fejlesztésben
Webinárium