Äsja nägime, kuidas väike lünk toob kaasa rahalise kahju (erineva ulatusega), samamoodi on Solidity kaudu välja töötatud nutikad lepingud altid erinevatele teadaolevatele ja tundmatutele rünnakutele. Ärakasutajad kasutavad vigu ja lünki, et piiluda nutikatesse lepingutesse ja manipuleerida nendega rünnakute läbiviimiseks. Siin esitame põhjaliku loendi 5 kõige sagedamini esinevast veast Solidity programmeerimiskeeles.
QuillAuditsis järgime adaptiivset metoodikat, et saada aru iga häkkimise olemusest ja rakendada selle õpetusi tulevaste nutikate lepingute kohta, et vältida võimalikke ohte.
Vead solidity programmeerimiskeeles
1. Märkimata väliskõne
Me tegeleme selle probleemiga ennekõike, sest see on üks kõige sagedamini täheldatud Solidity lõkse. Üldiselt saadetakse eeter mis tahes välisele kontole selle kaudu ülekandmine () funktsiooni. Peale selle on väliskõne tegemiseks kaks kõige enam kasutatavat funktsiooni; helistama()ja saada(), siin peamiselt helistama() funktsiooni kasutatakse laialdaselt arendajate poolt mitmekülgsete väliskõnede tegemiseks.
Kuigi helistama() ja saada() funktsioonid tagastavad tõeväärtuse, mis määrab, kas kõne õnnestus või mitte. Seega antud juhul, kui mõni funktsioonidest helistama() or saada() ei suuda ülesannet täita, naasevad nad a-ga vale Seega, kui arendaja ei kontrolli tagastusväärtust, muutub see lõksuks.
Haavatavus
Mõelge allolevale näitele:
lepingu Lotto{
boolpublic payedOut =vale;
pöörduge võitja avalikult;
uintpublic winAmount;
// … lisafunktsioonid siin
function sendToWinner()public{
nõuda(!payedOut);
võitja.send(winAmount);
väljamakstud = tõene;
}
function visszavontLeftOver()public{
nõuda(väljamakstud);
msg.sender.send(this.balance);
}
}
Ülaltoodud lotolaadses lepingus võime jälgida, et a võitja saab winAmount eeter, jättes veidi ülejääke, mida saab eemaldada mis tahes välisest ainest.
Siin on lepingu lõks real [11], kus a saatma kasutatakse ilma vastuse ristvalideerimiseta. Ülaltoodud näites a võitja kelle tehing ebaõnnestub (kas gaasi puudulikkuse tõttu või kui tegemist on lepinguga, mis tahtlikult lisab varufunktsiooni), volitab välja makstud olema seatud tõsi olenemata sellest, kas eetritehing õnnestus või mitte. Sel juhul võib iga ekspluateerija selle tagasi võtta võitja oma võidud kaudu välja võtma LeftOver funktsiooni.
QuillAuditi lähenemine
Meie ettevõttesisene arendajate meeskond tegeleb selle veaga, kasutades [ülekanne] asemel funktsioon [saada] funktsioon, kuna [ülekanne] taastub, kui välistehing taastub. Ja kui kasutate [saata], kontrollige alati tagastusväärtust.
Üks jõulisemaid lähenemisviise, mida järgime, on [taganemismustri] kasutamine. Siin isoleerime loogiliselt välise saatmisfunktsiooni ülejäänud koodibaasist ja asetame potentsiaalselt ebaõnnestunud tehingute pinge lõppkasutajale, kuna ta on see, kes kutsub tagasivõtmisfunktsiooni.
2. Taassisenemine
Ethereumi nutikad lepingud helistavad ja kasutavad teiste välislepingute koode ning selle läbiviimiseks peavad lepingud esitama väliskõnesid. Need väliskõned on haavatavad ja altid rünnakutele, üks selline rünnak toimus hiljuti DAO häkkimise puhul.
Haavatavus
Ründajad sooritavad selliseid rünnakuid, kui leping saadab eetri tundmatule aadressile. Sel juhul saab ründaja luua lepingu välisaadressil, millel on varufunktsioonis pahatahtlik kood, ja see pahatahtlik kood kutsutakse välja, kui leping saadab sellele aadressile eetri.
Fakt: Mõiste 'reentrancy' on loodud asjaolust, et kui väline pahatahtlik leping kutsub funktsiooni haavatava lepingu kaudu ja seejärel koodi täitmistee "siseneb" sellesse uuesti.
Mõelge allolevale näitele, see on Ethereumi varahoidla, mis võimaldab hoiustajatel nädalas välja võtta vaid 1 eetri.
leping EtherStore {
uint256 avalik väljavõtmineLimit = 1 eeter;
mapping(aadress => uint256) public lastWithdrawTime;
mapping(aadress => uint256) avalikud saldod;
function depositFunds() väline maksetav {
saldod[saatja] += sõnumi väärtus;
}
function returnFunds (uint256 _weiToWithdraw) public {
nõuda(saldod[sõnum.saatja] >= _weiToWithdraw);
// piirata tagasivõtmist
nõuda(_weiToWithdraw <= visszavonmislimiit);
// piirata väljavõtmise aega
nõuda(now >= lastWithdrawTime[sõnum.saatja] + 1 nädal);
nõuda(msg.sender.call.value(_weiToWithdraw)());
saldod[msg.sender] -= _weiToWithdraw;
lastWithdrawTime[msg.sender] = praegu;
}
}
Ülaltoodud lepingus on meil kaks avalikku funktsiooni: [depositFunds] ja [drawFunds]. [depositFunds] kasutatakse saatja saldo suurendamiseks, samas kui [drawFunds] määrab väljavõetava summa. Sel juhul on edu, kui väljavõetav summa on väiksem kui 1 eeter.
Lõks peitub siin joones [17], kus toimub eetri ülekanne. Ründaja võib luua pahatahtliku lepingu, mille ainsa konstruktori parameetrina on [EtherStores] lepingu aadress. See muudaks [etherStore'i] avalikuks muutujaks, mis on seetõttu rünnatavam.
QuilllAuditi lähenemine
Järgime erinevaid tehnikaid, et vältida nutikate lepingute võimalikke uuesti sisenemise haavatavusi. Kõige esimene ja parim võimalik viis on sisseehitatud [transfer] funktsiooni kasutamine eetri ülekandmisel mis tahes välisesse lepingusse.
Teiseks on oluline jälgida, et kõik olekumuutujate loogilised muudatused oleks tehtud enne eetri lepingust väljasaatmist. Näites [EtherStore] tuleks read [18] ja [19] panna enne rida [17].
Kolmandat tehnikat saab kasutada ka uuesti sisenevate kõnede vältimiseks; mutexi kasutuselevõtu kaudu. See on olekumuutuja lisand, mis lukustab lepingu koodi täitmise ajal.
3. Vaikimisi nähtavused
Soliditys kasutatavate funktsioonide jaoks on nähtavuse spetsifikaadid ja need määravad, kuidas neid saab kutsuda. Funktsioonide kutsumise määrab nähtavus; väliselt kasutajate poolt, muude tuletatud lepingutega, ainult sisemiselt või ainult väliselt. Vaatame, kuidas nähtavuse spetsifikaatorite ekslik kasutamine võib nutikates lepingutes põhjustada tohutut haavatavust.
Haavatavus
Vaikimisi on funktsiooni nähtavus [avalik], seega saavad välised kasutajad funktsioone kutsuda ilma konkreetse nähtavuseta. Viga tekib siis, kui arendajad unustavad määrata nähtavuse funktsioonidele, mis peaksid olema privaatsed (või mida saab lepingus endas välja kutsuda). Näiteks;
leping HashForEther {
function visszavonmineWinnings() {
// Võitja, kui aadressi viimased 8 kuueteistkümnendmärki on 0
nõuda(uint32(sõnumi saatja) == 0);
_sendWinnings();
}
function _sendWinnings() {
msg.sender.transfer(this.balance);
}
}
Ülaltoodud leping on lihtne aadressi äraarvamise pearahamäng. Siin näeme, et funktsioonide nähtavus ei ole määratud, eriti funktsioon [ _sendWinnings] on [avalik] (vaikimisi), seega saab selle välja kutsuda mis tahes aadressi kaudu, et varastada hüve.
QuillAuditi lähenemine
Meie sisemeeskond koosneb staažikatest arendajatest, kes järgivad alati parimaid audititavasid, siin tuleks selgelt välja tuua funktsioonide nähtavus, isegi kui neid soovitakse avalikult hoida, tuleb see ära mainida.
4. Konstruktorite kasutamise kaitsmine
Üldiselt nimetatakse konstruktoreid erifunktsioonideks, mida kasutatakse kriitiliste ja privilegeeritud ülesannete täitmiseks lepingute lähtestamise ajal. Enne Solidity [v0.4.22] kandsid konstruktorid sama nime, mida kasutas neid sisaldav leping. Mõelge nüüd juhtumile, kus lepingu nime muudetakse arendusfaasis, kuid ehitaja nimi jääb samaks. See lünk võib samuti pakkuda ründajatele hõlpsat juurdepääsu teie nutikale lepingule.
Haavatavus
See võib kaasa tuua tõsiseid tagajärgi, kui lepingu nime muudetakse, kuid ehitaja nime ei muudeta. Näiteks:
leping OwnerWallet {
aadress avalik omanik;
// konstruktor
function omanik Rahakott(aadress _omanik) public {
omanik = _omanik;
}
// Tagavara. Koguge eetrit.
funktsioon () makstav {}
function visszavon() public {
nõudma(msg.sender == omanik);
msg.sender.transfer(this.balance);
}
}
Ülaltoodud lepingus näeme, et ainult omanik saab eetri välja võtta funktsiooni [väljavõte] kaudu. Siin ilmneb haavatavus, kuna konstruktori nimi on lepingust erinev (esimene täht on erinev!). Seega saab ärakasutaja helistada funktsioonile [ownerWallet] ja volitada end omanikuks ning seejärel tühistada kogu lepingus oleva eetri, helistades [taanda].
QuillAuditi lähenemine
Me järgime Solidity kompilaatori versiooni [0.4.22]. See versioon sisaldab märksõna; [konstruktor], mis nõuab, et funktsiooni nimi ühtiks lepingu nimega.
5. Tx.Origin autentimine
Siin on [Tx.Origin] Solidity globaalne muutuja, see sisaldab algselt kõne või tehingu sooritanud konto aadressi. Seda muutujat ei saa autentimiseks kasutada, kuna see muudab lepingu andmepüügirünnakute suhtes haavatavaks.
Haavatavus
Lepingud, mis autoriseerivad kasutajaid muutuja [tx.origin] kaudu, puutuvad kokku väliste rünnakutega, mis sunnivad kasutajaid sooritama eksliku lepinguga autentitud toiminguid. Kaaluge allolevat näidet:
leping andmepüügiga {
aadress avalik omanik;
konstruktor (aadress _omanik) {
omanik = _omanik;
}
funktsioon () väline makstav {} // koguda eeter
function visszavonKõik(aadress _saaja) public {
nõuda(tx.origin == omanik);
_saaja.transfer(this.balance);
}
}
Siin real [11] volitab leping funktsiooni [tx.origin] abil funktsiooni [tx.origin].
QuillAuditi lähenemine
Üldiselt väldime nutikate lepingute autoriseerimiseks [tx.origin] kasutamist. Kuigi faili [tx.origin] kasutamine ei ole rangelt keelatud, on sellel teatud kasutusjuhtumeid. Me saame kasutada [tx.origin], et keelata väliste lepingute kutsumine käesolevale lepingule, seda saab täita vormiga [require] [require(tx.origin == msg.sender)]. Seda tehakse selleks, et vältida vahelepingute helistamist kehtivale lepingule, mis piirab lepingu tavaliste koodita aadressidega.
Lõplik kokkuvõte
Oleme põhjalikult käsitlenud Solidity keele viit levinud lõksu. Nutikate lepingute väljatöötamisel ei tohi me unustada, et need on disainilt muutumatud, mis tähendab, et kui oleme need loonud, ei saa lähtekoodi enam kuidagi parandada.
See seab arendajatele suure väljakutse kasutada enne juurutamist saadaolevaid turbetestimise ja auditeerimise tööriistu.
Nutikate lepingute võimalike pahatahtlike ohtude ja mõnede eespool mainitud riskide avastamist teostab meie ettevõttesisene auditiekspertide meeskond väga ainulaadsel ja jõulisel viisil. Meie, QuillAudits, anname oma parimad jõupingutused turbeuuringuteks, et hoida teie lepingut ajakohasena kõigi tarkvaraturbepraktikatega, et teie leping oleks turvaline.
Pöörduge QuillHashi poole
Aastate jooksul tööstuses QuillHash on tarninud ettevõtte lahendusi kogu maailmas. QuillHash koos ekspertide meeskonnaga on juhtiv plokiahelate arendusettevõte, mis pakub erinevaid tööstusharulahendusi, sealhulgas DeFi ettevõte. Kui vajate nutikate lepingute auditeerimisel abi, pöörduge julgelt meie ekspertide poole leiad siit!
Järgige värskenduste saamiseks rakendust QuillHash
puperdama | LinkedIn | Facebook
Allikas: https://blog.quillhash.com/2021/06/04/top-5-common-errors-in-solidity-programming-language/
- 11
- konto
- ADEelis
- Materjal: BPA ja flataatide vaba plastik
- audit
- Autentimine
- luba
- BEST
- blockchain
- Bug
- vead
- helistama
- juhtudel
- Põhjus
- väljakutse
- kood
- ühine
- ettevõte
- leping
- lepingud
- Praegune
- DAO
- Defi
- Disain
- arendaja
- Arendajad
- & Tarkvaraarendus
- ettevõte
- Eeter
- ethereum
- sündmus
- ekspertide
- finants-
- esimene
- järgima
- vorm
- tasuta
- funktsioon
- tulevik
- mäng
- GAS
- Globaalne
- suur
- näksima
- siin
- Kuidas
- HTTPS
- tohutu
- Kaasa arvatud
- tööstus
- IT
- keel
- viima
- juhtivate
- joon
- nimekiri
- Vastama
- Muu
- omanik
- Plaaster
- Muster
- Phishing
- andmepüügirünnakud
- määrama
- esitada
- era-
- Programming
- avalik
- tõmmates
- teadustöö
- vastus
- REST
- ohutu
- turvalisus
- Teenused
- komplekt
- lihtne
- väike
- nutikas
- arukas leping
- Tarkvaralepingud
- So
- tarkvara
- kindlus
- Lahendused
- riik
- edu
- Testimine
- Allikas
- ähvardused
- aeg
- ülemine
- top 5
- tehing
- Tehingud
- us
- Kasutajad
- väärtus
- võlvkelder
- nähtavus
- Haavatavused
- haavatavus
- Haavatav
- nädal
- WHO
- jooksul
- aastat