Pravkar smo videli, kako majhna vrzel vodi do finančne izgube (različne velikosti), na podoben način pa so pametne pogodbe, razvite v Solidityju, nagnjene k različnim znanim in neznanim napadom. Izkoriščevalci izkoriščajo napake in vrzeli, da pokukajo v pametne pogodbe in z njimi manipulirajo za izvajanje napadov. Tukaj predstavljamo izčrpen seznam 5 najpogostejših napak v programskem jeziku Solidity.
Pri QuillAudits sledimo prilagodljivi metodologiji, da dobimo bistvo vsakega vdora in uporabimo svoja spoznanja o prihodnjih pametnih pogodbah, da se izognemo morebitni grožnji.
Napake v trdnem programskem jeziku
1. Neznačen zunanji klic
To vprašanje najprej vlečemo, ker je ena najpogostejših pasti Solidity. Na splošno pošiljanje etra na kateri koli zunanji račun poteka prek prenos () funkcijo. Poleg tega sta dve najpogosteje uporabljeni funkciji za zunanji klic: pokliči ()in pošlji (), tukaj predvsem pokliči () funkcija se razvijalci pogosto uporabljajo za izvajanje vsestranskih zunanjih klicev.
Čeprav je pokliči () in pošlji () funkcije vrnejo logično vrednost, ki določa, ali je bil klic uspešen ali ne. Tako v tem primeru, če katera od funkcij pokliči () or pošlji () ne opravi naloge, se vrnejo z lažno Če torej razvijalec ne preveri vrnjene vrednosti, bi to postalo past.
Ranljivost
Upoštevajte spodnji primer:
pogodba Lotto {
boolpublic payedOut = false;
nagovoriti javnega zmagovalca;
uintpublic winAmount;
//… tu dodatna funkcionalnost
funkcija sendToWinner () public {
Zahtevaj (! payedOut);
winner.send (winAmount);
payedOut = true;
}
funkcija povlečiLeftOver () javno {
zahtevajo (plačanoOut);
msg.sender.send (this.balance);
}
}
V zgoraj navedeni Loto podobni pogodbi lahko opazimo, da a Zmagovalec prejme winAmount etra, ki pušča malo ostankov, ki jih je treba umakniti iz katerega koli zunanjega sredstva.
Tu obstaja zamka za pogodbo v vrstici [11], kjer a pošljite se uporablja brez navzkrižne potrditve odgovora. V zgornjem primeru a Zmagovalec katerih transakcija ne uspe (bodisi zaradi pomanjkanja plina bodisi če gre za pogodbo, ki namerno vključuje rezervno funkcijo), dovoli plačanoOut da se nastavi na Res ne glede na to, ali je bila transakcija etra uspešna ali ne. V tem primeru lahko kateri koli izkoriščevalec umakne zmagovalca dobitki prek umikLeftOver Funkcija.
Pristop QuillAudit
Naša interna ekipa razvijalcev se te napake loti z uporabo [prenos] namesto [pošlji] funkcijo, saj se bo [prenos] vrnil, če se zunanja transakcija povrne. In če uporabljate [send], vedno navzkrižno preverite vrnjeno vrednost.
Eden od trdnih pristopov, ki se mu držimo, je uporaba [vzorca umika]. Tu logično ločimo zunanjo funkcijo pošiljanja od ostale kode in na končnega uporabnika naložimo potencialno neuspešne transakcije, saj je ta tisti, ki pokliče funkcijo umika.
2. Ponovni vstop
Pametne pogodbe Ethereum kličejo in uporabljajo kode iz drugih zunanjih pogodb, zato morajo pogodbe oddati zunanje klice. Ti zunanji klici so ranljivi in nagnjeni k napadom, en tak napad se je pred kratkim zgodil v primeru kramp DAO.
Ranljivost
Napadalci izvajajo take napade, ko pogodba pošlje eter na neznan naslov. V tem primeru lahko napadalec ustvari pogodbo na zunanjem naslovu, ki ima v nadomestni funkciji zlonamerno kodo, in ta zlonamerna koda se bo sprožila, ko bo pogodba poslala eter na ta naslov.
Dejstvo: Izraz "ponovna vstopnost" je nastal iz dejstva, da ko zunanja zlonamerna pogodba pokliče funkcijo nad ranljivo pogodbo in jo pot izvajanja kode "ponovno vnese".
Upoštevajte spodnji primer, gre za trezor Ethereum, ki vlagateljem omogoča umik le 1 etra na teden.
pogodba EtherStore {
uint256 javni umikLimit = 1 eter;
preslikava (naslov => uint256) public lastWithdrawTime;
preslikava (naslov => uint256) javnih bilanc;
function depositFunds () zunanje plačilo {
stanja [sporočilo pošiljatelja] + = vrednost sporočila;
}
funkcija povučiFunds (uint256 _weiToWithdraw) javni {
zahteva (stanja [sporočilo pošiljatelja]> = _weiToWithdraw);
// omeji umik
zahteva (_weiToWithdraw <= umikLimit);
// omejimo čas, dovoljen za umik
zahteva (zdaj> = lastWithdrawTime [msg.sender] + 1 teden);
zahteva (msg.sender.call.value (_weiToWithdraw) ());
stanja [msg.sender] - = _weiToWithdraw;
lastWithdrawTime [msg.sender] = zdaj;
}
}
V zgornji pogodbi imamo dve javni funkciji, [DepositFunds] in [umikFunds]. [DepositFunds] se uporablja za povečanje pošiljateljevega stanja, medtem ko [pullFunds] določa znesek, ki ga je treba dvigniti. V tem primeru bo uspeh, če bo znesek za dvig manjši od 1 etra.
Pasti tu leži v vrsti [17], kjer poteka prenos etra. Napadalec bi lahko ustvaril zlonamerno pogodbo z naslovom pogodbe [EtherStores] kot edinim parametrom konstruktorja. S tem bi [etherStore] postala javna spremenljivka, zato je bolj nagnjena k napadom.
QuilllAuditov pristop
Upoštevamo različne tehnike, da se izognemo morebitnim ponovnim vstopom v pametne pogodbe. Prvi in najboljši možen način je uporaba vgrajene funkcije [prenos] pri prenosu etra na katero koli zunanjo pogodbo.
Drugič, pomembno je zagotoviti, da se pred pošiljanjem etra iz pogodbe izvedejo vse logične spremembe spremenljivk stanja. V primeru [EtherStore] je treba vrstici [18] in [19] postaviti pred vrstico [17].
Tretja tehnika se lahko uporablja tudi za preprečevanje ponovnih klicev; z uvedbo mutexa. Je dodatek spremenljivke stanja, ki bo zaklenila pogodbo med izvajanjem kode.
3. Privzete vidnosti
Obstajajo specifikatorji vidnosti za funkcije, ki jih uporabljamo v Solidity, in predpisujejo način, kako jih lahko pokličemo. Klicanje funkcij določa vidnost; zunaj s strani uporabnikov, z drugimi izpeljanimi pogodbami, samo znotraj ali samo navzven. Poglejmo, kako lahko napačna uporaba specifikatorjev vidnosti povzroči veliko ranljivost pri pametnih pogodbah.
Ranljivost
Privzeto je vidnost funkcije [javna], zato lahko zunanji uporabniki pokličejo funkcije brez posebne vidnosti. Napaka se pojavi, ko razvijalci pozabijo določiti vidnost funkcij, ki bi morale biti zasebne (ali jih je mogoče poklicati v sami pogodbi). Na primer;
pogodba HashForEther {
funkcija povučiZasluge () {
// Zmagovalec, če je zadnjih 8 šestnajstiških znakov naslova 0
zahteva (uint32 (msg.sender) == 0);
_sendWinnings ();
}
function _sendWinnings () {
msg.sender.transfer (this.balance);
}
}
Zgornja pogodba je preprosta igra z ugankanjem naslovov. V tem lahko vidimo, da vidnost funkcij ni določena, še posebej funkcija [_sendWinnings] je [javna] (privzeto), zato jo je mogoče poklicati prek katerega koli naslova, da ukrade nagrado.
Pristop QuillAudit
Naša interna ekipa je sestavljena iz prekaljenih razvijalcev, ki vedno sledijo najboljšim revizijskim praksam, pri tem pa je treba izrecno določiti vidnost funkcij, tudi če naj bodo javne, je treba omeniti.
4. Zaščita uporabe konstruktorjev
Na splošno se konstruktorji imenujejo posebne funkcije, ki se uporabljajo za izvajanje kritičnih in privilegiranih nalog med inicializacijo pogodb. Pred Solidity [v0.4.22] so bili konstruktorji z istim imenom, uporabljenim v pogodbi, ki jih je vsebovala. Zdaj pa razmislite o primeru, ko se ime pogodbe spremeni v fazi razvoja, vendar ime konstruktorja ostane enako, lahko ta vrzel napadalcem omogoči enostaven vstop v vašo pametno pogodbo.
Ranljivost
Če se ime pogodbe spremeni, ime konstruktorja pa se ne spremeni, lahko povzroči hude posledice. Na primer:
pogodba OwnerWallet {
nagovoriti javnega lastnika;
// konstruktor
funkcija ownerWallet (naslov _owner) public {
lastnik = _lastnik;
}
// Pasti nazaj. Zberite eter.
funkcija () plačljivo {}
funkcija povuči () javno {
zahteva (msg.sender == lastnik);
msg.sender.transfer (this.balance);
}
}
V zgornji pogodbi lahko vidimo, da lahko samo lastnik umakne eter s klicem funkcije [umik]. Tu pride do ranljivosti, ko je konstruktor imenovan drugače kot pogodba (prva črka je drugačna!). Tako lahko izkoriščevalec pokliče funkcijo [ownerWallet] in se pooblasti za lastnika ter nato prekine ves eter v pogodbi s klicem [umik].
Pristop QuillAudit
Upoštevamo različico [0.4.22] prevajalnika Solidity. Ta različica je predstavila ključno besedo; [konstruktor], ki zahteva, da se ime funkcije ujema z imenom pogodbe.
5. Preverjanje pristnosti izvornega izvora
Tu je [Tx.Origin] globalna spremenljivka Solidity, vsebuje naslov računa, ki je prvotno izvedel klic ali transakcijo. Te spremenljivke ni mogoče uporabiti za preverjanje pristnosti, saj je s tem pogodba ranljiva za phishing napade.
Ranljivost
Pogodbe, ki pooblaščajo uporabnike prek spremenljivke [tx.origin], so izpostavljene zunanjim napadom, zaradi katerih uporabniki izvajajo overjena dejanja v zvezi z napačno pogodbo. Upoštevajte spodnji primer:
pogodba Izmenljivo {
nagovoriti javnega lastnika;
konstruktor (naslov _owner) {
lastnik = _lastnik;
}
function () zunanje plačljivo {} // zbiraj eter
funkcija povlecite vse (naslov _prejemnik) javni {
zahtevaj (tx.origin == lastnik);
_recipient.transfer (this.balance);
}
}
Tu v vrstici [11] pogodba s pomočjo [tx.origin] dovoljuje funkcijo [povuči vse].
Pristop QuillAudit
Običajno se izogibamo uporabi [tx.origin] za avtorizacijo v pametnih pogodbah. Čeprav uporaba [tx.origin] ni strogo prepovedana, ima nekaj posebnih primerov uporabe. Z [tx.origin] lahko zavrnemo zunanje pogodbe, da bi poklicali sedanjo pogodbo, izvedemo pa jo lahko z [require] v obliki [require (tx.origin == msg.sender)]. To se naredi, da bi se izognili sklicu vmesnih pogodb, da bi poklicali trenutno pogodbo, ki omejuje pogodbo na običajne brezšifrene naslove.
Končni zaključek
Izčrpno smo obravnavali pet pogostih pasti v jeziku Solidity. Pri razvoju pametnih pogodb ne smemo pozabiti, da so po zasnovi nespremenljive, kar pomeni, da ko jih enkrat izdelamo, ni mogoče popraviti izvorne kode.
To razvijalcem predstavlja velik izziv, da izkoristijo razpoložljiva orodja za testiranje in revizijo varnosti pred uvedbo.
Odkrivanje potencialnih zlonamernih groženj pametnim pogodbam in tveganj, ki smo jih omenili zgoraj, naša interna skupina revizijskih strokovnjakov izvaja na zelo edinstven in močan način. QuillAudits si po najboljših močeh prizadevamo za raziskave varnosti, da bo vaša pogodba posodobljena z vsemi praksami varovanja programske opreme, da bo vaša pogodba varna.
Obrnite se na QuillHash
Z dolgoletno prisotnostjo v industriji, QuillHash je rešitve za podjetja predstavil po vsem svetu. QuillHash z ekipo strokovnjakov je vodilno podjetje za razvoj verig blokov, ki ponuja različne industrijske rešitve, vključno s podjetjem DeFi. Če potrebujete kakršno koli pomoč pri reviziji pametnih pogodb, se obrnite na naše strokovnjake tukaj!
Sledite QuillHash za več posodobitev
Vir: https://blog.quillhash.com/2021/06/04/top-5-common-errors-in-solidity-programming-language/
- 11
- Račun
- Prednost
- vsi
- Revizija
- Preverjanje pristnosti
- pooblastilo
- BEST
- blockchain
- Bug
- hrošči
- klic
- primeri
- Vzrok
- izziv
- Koda
- Skupno
- podjetje
- Naročilo
- pogodbe
- Trenutna
- DAO
- Defi
- Oblikovanje
- Razvojni
- Razvijalci
- Razvoj
- Podjetje
- Eter
- ethereum
- Event
- Strokovnjaki
- finančna
- prva
- sledi
- obrazec
- brezplačno
- funkcija
- Prihodnost
- igra
- GAS
- Globalno
- veliko
- kramp
- tukaj
- Kako
- HTTPS
- velika
- Vključno
- Industrija
- IT
- jezik
- vodi
- vodi
- vrstica
- Seznam
- Stave
- Ostalo
- Lastnik
- Patch
- Vzorec
- Ribarjenje
- lažni napadi
- predpiše
- predstaviti
- zasebna
- Programiranje
- javnega
- vlečenje
- Raziskave
- Odgovor
- REST
- varna
- varnost
- Storitve
- nastavite
- Enostavno
- majhna
- pametna
- pametna pogodba
- Pametne pogodbe
- So
- Software
- trdnost
- rešitve
- Država
- uspeh
- Testiranje
- Vir
- grožnje
- čas
- vrh
- top 5
- transakcija
- Transakcije
- us
- Uporabniki
- vrednost
- Vault
- vidljivost
- Ranljivosti
- ranljivost
- Ranljivi
- teden
- WHO
- v
- let