Az imént láthattuk, hogy egy kis kibúvó hogyan vezet (változó nagyságrendű) anyagi veszteséghez, ehhez hasonlóan a Solidity felett kifejlesztett okosszerződések is hajlamosak különféle ismert és ismeretlen támadásokra. A kizsákmányolók kihasználják a hibákat és a kiskapukat, hogy bekukucskáljanak az intelligens szerződésekbe, és manipulálják azokat támadások végrehajtására. Az alábbiakban bemutatjuk a Solidity programozási nyelv 5 leggyakrabban előforduló hibájának átfogó listáját.
A QuillAuditsnál az adaptív módszertant követjük, hogy megértsük minden feltörés lényegét, és a jövőbeni intelligens szerződésekkel kapcsolatos tanulságokat alkalmazzuk, hogy elkerüljük a potenciális veszélyeket.
Hibák a solidity programozási nyelvben
1. Nincs bejelölve Külső hívás
Elsősorban azért húzzuk ezt a problémát, mert ez a Solidity egyik leggyakrabban megfigyelt buktatója. Általában az étert bármely külső számlára küldik a átruházás() funkció. Ezen kívül a két legszélesebb körben használt funkció a külső hívások kezdeményezésére; hívás()és Küld(), itt főleg a hívás() A funkciót széles körben használják a fejlesztők sokoldalú külső hívások végrehajtására.
Bár a hívás() és a Küld() függvények logikai értéket adnak vissza, amely megadja, hogy a hívás sikeres volt-e vagy sem. Így ebben az esetben, ha valamelyik függvény hívás() or Küld() nem hajtja végre a feladatot, akkor a hamis. Ezért, ha a fejlesztő nem ellenőrzi a visszatérési értéket, az buktatóvá válna.
A biztonsági rés
Tekintsük az alábbi példát:
szerződés Lotto{
boolpublic payedOut =false;
nyilvános nyertes megszólítása;
uintpublic winAmount;
// … extra funkciók itt
function sendToWinner()public{
igényel(!payedOut);
győztes.send(winAmount);
payedOut =igaz;
}
function drawLftOver()public{
megkövetel(kifizetett);
msg.sender.send(this.balance);
}
}
A fenti Lotto-szerű szerződésben megfigyelhetjük, hogy a győztes kap winAmount étert hagyva egy kis maradékot, amit bármilyen külső ágensből ki kell vonni.
Itt a szerződés buktatója a [11] vonalon van, ahol a küld a válasz keresztellenőrzése nélkül használják. A fenti példában a győztes akinek a tranzakciója meghiúsul (akár a gáz hiánya miatt, akár ha olyan szerződésről van szó, amely szándékosan bedobja a tartalék funkciót), engedélyezi kifizetett be kell állítani igaz függetlenül attól, hogy az éter tranzakció sikeres volt-e vagy sem. Ebben az esetben bármely kihasználó visszavonhatja a nyertesé nyeremény a visszavonja LeftOver funkciót.
A QuillAudit megközelítése
Házon belüli fejlesztői csapatunk a következő használatával kezeli ezt a hibát [átruházás] funkció helyett [Küld] függvényt, mivel az [átvitel] visszaáll, ha a külső tranzakció visszaáll. És ha a [send] parancsot használja, mindig ellenőrizze a visszatérési értéket.
Az általunk követett egyik robusztus megközelítés a [kivonási minta] alkalmazása. Itt logikailag elkülönítjük a külső küldési funkciót a kódbázis többi részétől, és a potenciálisan sikertelen tranzakciók terhelését a végfelhasználóra helyezzük, mivel ő hívja meg a visszavonási függvényt.
2. Újbóli belépés
Az Ethereum okosszerződések más külső szerződésekből származó kódokat hívnak és hasznosítanak, ennek lebonyolításához a szerződéseknek külső hívást kell benyújtaniuk. Ezek a külső hívások sebezhetőek és támadásokra hajlamosak, az egyik ilyen támadás a közelmúltban történt a DAO feltörése esetén.
A biztonsági rés
A támadók akkor hajtanak végre ilyen támadásokat, amikor egy szerződés étert küld egy ismeretlen címre. Ebben az esetben a támadó létrehozhat egy szerződést egy külső címen, amely rosszindulatú kódot tartalmaz a tartalék funkcióban, és ezt a rosszindulatú kódot a rendszer meghívja, amikor a szerződés étert küld erre a címre.
Tény: A „Reentrancy” kifejezést abból a tényből találták ki, hogy amikor egy külső rosszindulatú szerződés meghív egy funkciót a sérülékeny szerződésen, majd a kódvégrehajtási útvonal „újra belép” abba.
Tekintsük az alábbi példát, ez egy Ethereum trezor, amely lehetővé teszi a betétesek számára, hogy hetente csak 1 etert vegyenek fel.
szerződés EtherStore {
uint256 nyilvános visszavonásLimit = 1 éter;
leképezés(cím => uint256) public lastWithdrawTime;
mapping(cím => uint256) nyilvános egyenlegek;
function depositFunds() külső fizetendő {
egyenlegek[üzenetküldő] += msg.value;
}
function drawFunds (uint256 _weiToWithdraw) public {
igényel(egyenlegek[üzenetküldő] >= _weiToWithdraw);
// korlátozza a visszavonást
request(_weiToWithdraw <= visszavonásLimit);
// korlátozza a visszavonásra engedélyezett időt
request(now >= lastWithdrawTime[üzenetküldő] + 1 hét);
request(msg.sender.call.value(_weiToWithdraw)());
egyenlegek[üzenetküldő] -= _weiToWithdraw;
lastWithdrawTime[msg.sender] = most;
}
}
A fenti szerződésben két nyilvános funkciónk van, a [depositFunds] és a [drawFunds]. A [depositFunds] a feladó egyenlegének növelésére szolgál, míg a [withdrawFunds] határozza meg a felvenni kívánt összeget. Ebben az esetben az lesz a siker, ha a felvenni kívánt összeg kevesebb, mint 1 éter.
A buktató itt a [17] sorban van, ahol az éter átvitele megtörténik. A támadó rosszindulatú szerződést hozhat létre, amelynek egyetlen konstruktor paramétere az [EtherStores] szerződéscíme. Ez az [etherStore]-t nyilvános változóvá tenné, így jobban ki van téve a támadásoknak.
A QuilllAudit megközelítése
Különféle technikákat követünk annak érdekében, hogy elkerüljük az intelligens szerződések esetleges visszatérési sebezhetőségét. A legelső és a lehető legjobb módszer a beépített [transfer] funkció használata, amikor étert bármilyen külső szerződésre átvisz.
Másodszor, fontos annak biztosítása, hogy az állapotváltozókban minden logikai változtatást meg kell tenni az éter szerződésből való kiküldése előtt. Az [EtherStore] példában a [18] és [19] sorokat a [17] sor elé kell tenni.
Egy harmadik technika is használható a visszatérő hívások megelőzésére; mutex bevezetése révén. Ez egy állapotváltozó kiegészítése, amely zárolja a szerződést a kód végrehajtása során.
3. Alapértelmezett láthatóságok
A Solidity-ben használt függvényeknek vannak láthatósági specifikációi, és ezek határozzák meg, hogyan hívhatók meg. A láthatóság határozza meg a függvények meghívását; külsőleg a felhasználók által, más származtatott szerződésekkel, csak belsőleg vagy csak külsőleg. Nézzük meg, hogy a láthatósági specifikációk hibás használata miként okozhat óriási sebezhetőséget az intelligens szerződésekben.
A biztonsági rés
Alapértelmezés szerint a függvény láthatósága [nyilvános], így a külső felhasználók külön láthatóság nélkül hívhatják meg a függvényeket. A hiba akkor jelentkezik, amikor a fejlesztők elfelejtik megadni a láthatóságot azoknál a funkcióknál, amelyeknek privátnak kell lenniük (vagy magán a szerződésen belül hívhatók meg). Például;
szerződés HashForEther {
function visszavonjaWinnings() {
// Győztes, ha a cím utolsó 8 hexadecimális karaktere 0
igény(uint32(üzenetküldő) == 0);
_sendWinnings();
}
function _sendWinnings() {
msg.sender.transfer(this.balance);
}
}
A fenti szerződés egy egyszerű címkitalálós jutalomjáték. Ebben azt láthatjuk, hogy a függvények láthatósága nincs megadva, különösen a [ _sendWinnings] függvény [public] (alapértelmezés szerint), így ez bármely címen keresztül meghívható a jutalom ellopása érdekében.
A QuillAudit megközelítése
Házon belüli csapatunk tapasztalt fejlesztőkből áll, akik mindig követik a legjobb audit gyakorlatokat, itt kifejezetten meg kell határozni a funkciók láthatóságát, még ha nyilvánosan is kívánják tartani, azt meg kell említeni.
4. A konstruktorok használatának védelme
A konstruktorokat általában speciális funkcióknak nevezik, amelyeket kritikus és kiemelt feladatok végrehajtására használnak a szerződések inicializálása közben. A Solidity [v0.4.22] előtt a konstruktőrök ugyanazt a nevet viselték, mint az őket tartalmazó szerződésben. Most vegyük fontolóra azt az esetet, amikor a szerződés neve megváltozik a fejlesztési szakaszban, de a kivitelező neve változatlan marad. Ez a kiskapu a támadók számára is könnyű hozzáférést biztosíthat az intelligens szerződéshez.
A biztonsági rés
Súlyos következményekkel járhat, ha a szerződésnév módosul, de a kivitelező neve nem változik. Például:
szerződés OwnerWallet {
cím nyilvános tulajdonos;
// konstruktor
function ownerWallet(cím _tulajdonos) public {
tulajdonos = _tulajdonos;
}
// Tartalék. Gyűjtsd össze az étert.
függvény () fizetendő {}
function visszavon() public {
request(msg.sender == tulajdonos);
msg.sender.transfer(this.balance);
}
}
A fenti szerződésben látható, hogy csak a tulajdonos vonhatja ki az étert a [visszavonás] függvény meghívásával. Itt a sérülékenység akkor következik be, amikor a konstruktor neve eltér a szerződéstől (az első betű más!). Így az exploiter meghívhatja a [ownerWallet] függvényt, és felhatalmazhatja magát tulajdonosként, majd visszavonhatja a szerződésben szereplő összes étert a [visszavonás] hívásával.
A QuillAudit megközelítése
Megfelelünk a Solidity fordító [0.4.22] verziójának. Ez a verzió bevezetett egy kulcsszót; [constructor], amely megköveteli, hogy a függvény neve megegyezzen a szerződés nevével.
5. Tx.Origin hitelesítés
Itt a [Tx.Origin] a Solidity globális változója, amely a hívást vagy tranzakciót eredetileg végrehajtó fiók címét tartalmazza. Ez a változó nem használható hitelesítésre, mivel ezzel a szerződést sebezhetővé teszi az adathalász támadásokkal szemben.
A biztonsági rés
A felhasználókat a [tx.origin] változón keresztül engedélyező szerződések külső támadásoknak vannak kitéve, amelyek arra késztetik a felhasználókat, hogy hitelesített műveleteket hajtsanak végre a hibás szerződésen. Tekintsük az alábbi példát:
szerződés adathalászat {
cím nyilvános tulajdonos;
konstruktor (cím _tulajdonos) {
tulajdonos = _tulajdonos;
}
függvény () külső fizetendő {} // étert gyűjt
function visszavonvaAll(cím _címzett) public {
request(tx.origin == tulajdonos);
_recipient.transfer(this.balance);
}
}
Itt a [11] sorban a szerződés a [tx.origin] segítségével engedélyezi a [withdrawAll] funkciót.
A QuillAudit megközelítése
Az intelligens szerződésekben általában kerüljük a [tx.origin] használatát az engedélyezéshez. Bár a [tx.origin] használata nem szigorúan tilos, van néhány speciális használati esete. A [tx.origin] segítségével megtagadhatjuk a jelen szerződés meghívását a külső szerződésektől, ez végrehajtható [require] formátumban [require(tx.origin == msg.sender)]. Ez azért történik, hogy elkerüljük a köztes szerződések lehívását az aktuális szerződés felhívására, amely a szerződést normál kód nélküli címekre korlátozza.
Végső összecsomagolás
A Solidity nyelvezetben átfogóan ismertettük az öt gyakori buktatót. Az intelligens szerződések fejlesztése során nem szabad megfeledkeznünk arról, hogy azok tervezésüknél fogva megváltoztathatatlanok, ami azt jelenti, hogy miután elkészítettük őket, nincs mód a forráskód javítására.
Ez nagy kihívás elé állítja a fejlesztőket, hogy kihasználják a rendelkezésre álló biztonsági tesztelési és auditáló eszközök előnyeit a telepítés előtt.
Az intelligens szerződéseket fenyegető potenciális rosszindulatú fenyegetések, valamint a fent említett kockázatok felderítése egyedi és robusztus módon a belső audit szakértői csapatunk által történik. Mi, a QuillAudits minden tőlünk telhetőt megteszünk a biztonsági kutatások terén, hogy a szerződését naprakészen tartsuk az összes szoftverbiztonsági gyakorlattal, hogy szerződése biztonságban legyen.
Forduljon QuillHashhoz
Évek óta jelen lévő iparágban, QuillHash vállalati megoldásokat szállított szerte a világon. A QuillHash egy szakértői csapattal egy vezető blokklánc-fejlesztő cég, amely különféle iparági megoldásokat kínál, beleértve a DeFi vállalati megoldásokat is. Ha segítségre van szüksége az intelligens szerződések auditjához, forduljon bizalommal szakértőinkhoz. itt!
További frissítésekért kövesse a QuillHash-t
Forrás: https://blog.quillhash.com/2021/06/04/top-5-common-errors-in-solidity-programming-language/
- 11
- Fiók
- Előny
- Minden termék
- könyvvizsgálat
- Hitelesítés
- meghatalmazás
- BEST
- blockchain
- Bogár
- bogarak
- hívás
- esetek
- Okoz
- kihívás
- kód
- Közös
- vállalat
- szerződés
- szerződések
- Jelenlegi
- DAO
- Defi
- Design
- Fejlesztő
- fejlesztők
- Fejlesztés
- Vállalkozás
- Éter
- Ethereum
- esemény
- szakértők
- pénzügyi
- vezetéknév
- következik
- forma
- Ingyenes
- funkció
- jövő
- játék
- GAS
- Globális
- nagy
- csapkod
- itt
- Hogyan
- HTTPS
- hatalmas
- Beleértve
- ipar
- IT
- nyelv
- vezet
- vezető
- vonal
- Lista
- Mérkőzés
- Más
- tulajdonos
- Tapasz
- Mintás
- Adathalászat
- adathalász támadások
- elő
- be
- magán
- Programozás
- nyilvános
- vontatás
- kutatás
- válasz
- REST
- biztonságos
- biztonság
- Szolgáltatások
- készlet
- Egyszerű
- kicsi
- okos
- okos szerződés
- Intelligens szerződések
- So
- szoftver
- szilárdság
- Megoldások
- Állami
- siker
- Tesztelés
- The Source
- fenyegetések
- idő
- felső
- top 5
- tranzakció
- Tranzakciók
- us
- Felhasználók
- érték
- Boltozat
- láthatóság
- sérülékenységek
- sebezhetőség
- Sebezhető
- hét
- WHO
- belül
- év