Vi har nettopp sett hvordan et lite smutthull fører til et økonomisk tap (av varierende størrelse), på samme måte som smarte kontrakter utviklet over soliditet er utsatt for forskjellige kjente og ukjente angrep. Utbytterne utnytter feil og smutthull for å se på smarte kontrakter og manipulere dem for å utføre angrep. Her presenterer vi en omfattende liste over de fem vanligste feilene i programmeringsspråket Solidity.
På QuillAudits følger vi den tilpasningsdyktige metoden for å få kjernen i hvert hack og implementere læring om fremtidige smarte kontrakter for å unngå potensiell trussel.
Feil i programmeringsspråk for soliditet
1. Ukontrollert ekstern samtale
Vi trekker dette problemet i utgangspunktet fordi det er en av de mest observerte fasthetsgruvene. Generelt, å sende eter til en ekstern konto utføres gjennom overføre() funksjon. Bortsett fra dette, er de to mest brukte funksjonene for å ringe eksternt; anrop()og sende(), her hovedsakelig anrop() funksjonen blir mye brukt til å utføre allsidige eksterne samtaler av utviklerne.
Selv om anrop() og sende() funksjoner returnerer en boolsk verdi som angir om samtalen var vellykket eller ikke. Dermed i dette tilfellet, hvis noen av funksjonene anrop() or sende() mislykkes i å utføre oppgaven, vil de gå tilbake med en falsk. Derfor, hvis utvikleren ikke kryssjekker returverdien, vil det bli en fallgruve.
Sårbarheten
Tenk på eksemplet nedenfor:
kontrakt Lotto {
boolpublic payedOut = false;
adresse offentlig vinner;
uintpublic winAmount;
// ... ekstra funksjonalitet her
funksjon sendToWinner () offentlig {
krever (! payedOut);
winner.send (winAmount);
payedOut = true;
}
funksjon trekke tilbakeLeftOver () offentlig {
krever (payedOut);
msg.sender.send (this.balance);
}
}
I den Lotto-lignende kontrakten ovenfor kan vi observere at a Vinner mottar winAmount av eter som etterlater litt rest som skal trekkes tilbake fra enhver ekstern agent.
Her finnes fallgruven for kontrakten på linje [11], hvor en send brukes uten kryssvalidering av svaret. I eksemplet ovenfor, a Vinner hvis transaksjon mislykkes (enten på grunn av mangel på gass eller hvis det er en kontrakt som med vilje kaster inn reservefunksjonen), godkjenner betalt ut som skal settes til sant uavhengig av om transaksjonen med eter var en suksess eller ikke. I dette tilfellet kan enhver utnytter trekke tilbake vinnerens gevinster via trekke ut LeftOver funksjon.
QuillAudits tilnærming
Vårt interne team av utviklere takler denne feilen ved bruk av [overføre] funksjon i stedet for [sende] funksjon, da [overføring] vil tilbakestilles hvis ekstern transaksjon går tilbake. Og hvis du bruker [send], kryssjekk alltid returverdien.
En av de robuste tilnærmingene vi følger er å bruke et [uttrekksmønster]. Her isolerer vi logisk den eksterne sendefunksjonaliteten fra resten av kodebasen, og legger belastningen på potensielt mislykkede transaksjoner på sluttbrukeren, da han er den som kaller tilbaketrekningsfunksjonen.
2. Gjeninngang
Ethereums smarte kontrakter ringer og bruker koder fra andre eksterne kontrakter, og for å gjennomføre dette, er kontraktene pålagt å sende eksterne samtaler. Disse eksterne samtalene er sårbare og utsatt for angrep, et slikt angrep skjedde nylig i tilfelle DAO-hack.
Sårbarheten
Angripere utfører slike angrep når en kontrakt sender eter til en ukjent adresse. I dette tilfellet kan angriperen opprette en kontrakt på en ekstern adresse som har skadelig kode i reservefunksjonen, og denne ondsinnede koden vil bli påkalt når kontrakten sender eter til denne adressen.
Faktum: Begrepet 'Reentrancy' har blitt laget fra det faktum at når en ekstern ondsinnet kontrakt kaller en funksjon over den sårbare kontrakten, og deretter kjører kodeutførelsesbanen den på nytt.
Tenk på eksemplet nedenfor, det er et Ethereum-hvelv som lar innskytere kun trekke ut 1 eter per uke.
kontrakt EtherStore {
uint256 offentlig tilbaketrekkingLimit = 1 eter;
kartlegging (adresse => uint256) offentlig lastWithdrawTime;
kartlegging (adresse => uint256) offentlige saldoer;
funksjon depositFunds () ekstern betales {
balanserer [msg.sender] + = msg.value;
}
funksjonsuttakFond (uint256 _weiToWithdraw) offentlig {
krever (saldoer [msg.sender]> = _weiToWithdraw);
// begrense uttaket
krever (_weiToWithdraw <= tilbaketrekningLimit);
// begrense tiden det er tillatt å trekke seg
krever (nå> = lastWithdrawTime [msg.sender] + 1 uke);
krever (msg.sender.call.value (_weiToWithdraw) ());
saldoer [msg.sender] - = _weiToWithdraw;
lastWithdrawTime [msg.sender] = nå;
}
}
I den ovennevnte kontrakten har vi to offentlige funksjoner, [innskuddsfond] og [uttaksfond]. [DepositFunds] brukes til å øke avsenderens saldo, mens [trekkfond] spesifiserer beløpet som skal trekkes ut. I dette tilfellet vil det være en suksess hvis beløpet som skal trekkes ut er mindre enn 1 eter.
Fallgruven her ligger i linje [17] der overføring av eter foregår. Angriperen kunne opprette en ondsinnet kontrakt med [EtherStores] sin kontraktadresse som den eneste konstruktørparameteren. Dette ville gjøre [etherStore] til en offentlig variabel, derav mer utsatt for å bli angrepet.
QuilllAudits tilnærming
Vi følger ulike teknikker for å unngå potensielle sårbarheter for reentrancy i smarte kontrakter. Den aller første og best mulige måten er bruken av den innebygde [overførings] -funksjonen når du overfører eter til en ekstern kontrakt.
For det andre er det viktig å sikre at alle logiske endringer i tilstandsvariablene skal gjøres før eter sendes ut av kontrakten. I [EtherStore] -eksemplet skal linjene [18] og [19] plasseres før linjen [17].
En tredje teknikk kan også brukes for å forhindre anrop om nye innflytelser; gjennom introduksjonen av en mutex. Det er et tillegg av en statlig variabel som vil låse kontrakten under kodeutførelse.
3. Standard synlighet
Det er synlighetsspesifikatorer for funksjonene vi bruker i Solidity, og de foreskriver måten de kan kalles på. Det er synligheten som bestemmer kallet til funksjonene; eksternt av brukere, ved andre avledede kontrakter, bare internt eller bare eksternt. La oss se på hvordan feil bruk av synlighetsspesifikatorer kan forårsake enorm sårbarhet i smarte kontrakter.
Sårbarheten
Som standard er synligheten av funksjonen [offentlig], og derfor kan eksterne brukere ringe til funksjonene uten spesifikk synlighet. Feilen oppstår når utviklere glemmer å spesifisere synlighet på funksjoner som skal være private (eller som kan kalles i selve kontrakten). For eksempel;
kontrakt HashForEther {
funksjonsuttakWinnings () {
// Vinner hvis de siste 8 sekskantede tegnene i adressen er 0
krever (uint32 (msg.sender) == 0);
_sendWinnings ();
}
funksjon _sendWinnings () {
msg.sender.transfer (this.balance);
}
}
Ovennevnte kontrakt er et enkelt adressegissende dusørspill. I dette kan vi se at synligheten til funksjonene ikke er spesifisert, spesielt [_sendWinnings] -funksjonen er [offentlig] (som standard), derfor kan dette kalles gjennom hvilken som helst adresse for å stjele dusøren.
QuillAudits tilnærming
Vårt interne team består av erfarne utviklere som alltid følger den beste revisjonspraksis, her skal synligheten til funksjonene spesifiseres eksplisitt, selv om de skal holdes offentlige, bør det nevnes.
4. Sikre bruken av konstruktører
Generelt kalles konstruktører spesialfunksjoner som brukes til å utføre kritiske og privilegerte oppgaver mens de initialiseres. Før Solidity [v0.4.22] hadde konstruktører samme navn som ble brukt i kontrakten som inneholdt dem. Vurder nå et tilfelle der kontraktsnavnet endres i utviklingsfasen, men konstruktørnavnet forblir det samme, dette smutthullet kan også gi angripere en enkel inngang til din smarte kontrakt.
Sårbarheten
Det kan føre til alvorlige konsekvenser hvis kontraktsnavnet endres, men konstruktørens navn er uendret. For eksempel:
kontrakt OwnerWallet {
adresse offentlig eier;
// konstruktør
funksjon eierWallet (adresse _ eier) offentlig {
eier = _ eier;
}
// Falle tilbake. Samle eter.
funksjon () betales {}
funksjon trekke tilbake () offentlig {
krever (msg.sender == eier);
msg.sender.transfer (this.balance);
}
}
I ovennevnte kontrakt kan vi se at bare eieren kan trekke eter ved å ringe [trekke] -funksjonen. Her oppstår sårbarheten når konstruktøren heter forskjellig fra kontrakten (første bokstav er annerledes!). Dermed kan exploiter ringe [eierWallet] -funksjonen og autorisere seg som eier, og deretter trekke tilbake all eteren i kontrakten ved å ringe [trekke].
QuillAudits tilnærming
Vi overholder versjon [0.4.22] av Solidity kompilatoren. Denne versjonen har introdusert et nøkkelord; [konstruktør] som krever at navnet på funksjonen samsvarer med kontraktsnavnet.
5. Tx.Origin Authentication
Her er [Tx.Origin] Solidides globale variabel, den inneholder adressen til kontoen som opprinnelig utførte samtalen eller transaksjonen. Denne variabelen kan ikke brukes til autentisering, da kontrakten er sårbar for phishing-angrep, da dette gjøres.
Sårbarheten
Kontrakter som autoriserer brukere gjennom [tx.origin] -variabelen, utsettes for eksterne angrep som fører til at brukere utfører godkjente handlinger på den feilaktige kontrakten. Tenk på eksemplet nedenfor:
kontrakt Phishable {
adresse offentlig eier;
konstruktør (adresse _ eier) {
eier = _ eier;
}
funksjon () ekstern betales {} // samle eter
funksjon trekkAlle (adresse _mottaker) offentlige {
krever (tx.origin == eier);
_recipient.transfer (denne.balansen);
}
}
Her på linje [11] godkjenner kontrakten funksjonen [trekkAll] ved hjelp av [tx.origin].
QuillAudits tilnærming
Vi unngår generelt å bruke [tx.origin] for autorisasjon i smarte kontrakter. Selv om bruken av [tx.origin] ikke er strengt forbudt, har den noen spesifikke brukssaker. Vi kan bruke [tx.origin] til å nekte eksterne kontrakter fra å ringe den nåværende kontrakten. Den kan utføres med [krever] av skjemaet [krever (tx.origin == msg.sender)]. Det er gjort for å unngå innkalling av mellomkontrakter for å ringe den gjeldende kontrakten, som begrenser kontrakten til vanlige kodeløse adresser.
Endelig avslutning
Vi har omfattende dekket de fem vanlige fallgruvene i Soliditetsspråket. Mens vi utvikler smarte kontrakter, må vi ikke glemme at de er uforanderlige av design, noe som betyr at når vi først har opprettet dem, er det ingen måte å lappe kildekoden.
Dette utgjør en stor utfordring for utviklere å dra nytte av tilgjengelige sikkerhetstestings- og revisjonsverktøy før distribusjon.
Å oppdage potensielle ondsinnede trusler mot smarte kontrakter, og risikoene som vi nevnte ovenfor, utføres på en veldig unik og robust måte av vårt interne team av revisjonseksperter. Vi i QuillAudits gjør vårt ytterste for sikkerhetsforskning for å holde kontrakten oppdatert med all sikkerhetspraksis for programvare for å holde kontrakten din trygg og sikker.
Nå ut til QuillHash
Med en nærvær i mange år, QuillHash har levert bedriftsløsninger over hele verden. QuillHash med et team av eksperter er et ledende blockchain-utviklingsselskap som tilbyr forskjellige bransjeløsninger, inkludert DeFi-virksomhet. her!
Følg QuillHash for flere oppdateringer
Kilde: https://blog.quillhash.com/2021/06/04/top-5-common-errors-in-solidity-programming-language/
- 11
- Logg inn
- Fordel
- Alle
- revisjon
- Autentisering
- autorisasjon
- BEST
- blockchain
- Bug
- bugs
- ring
- saker
- Årsak
- utfordre
- kode
- Felles
- Selskapet
- kontrakt
- kontrakter
- Gjeldende
- DAO
- Defi
- utforming
- Utvikler
- utviklere
- Utvikling
- Enterprise
- Eter
- ethereum
- Event
- eksperter
- finansiell
- Først
- følge
- skjema
- Gratis
- funksjon
- framtid
- spill
- GAS
- Global
- flott
- hack
- her.
- Hvordan
- HTTPS
- stort
- Inkludert
- industri
- IT
- Språk
- føre
- ledende
- linje
- Liste
- Match
- Annen
- eieren
- patch
- Mønster
- phishing
- phishing-angrep
- foreskrive
- presentere
- privat
- Programmering
- offentlig
- trekke
- forskning
- svar
- REST
- trygge
- sikkerhet
- Tjenester
- sett
- Enkelt
- liten
- Smart
- smart kontrakt
- Smarte kontrakter
- So
- Software
- soliditet
- Solutions
- Tilstand
- suksess
- Testing
- Kilden
- trusler
- tid
- topp
- top 5
- Transaksjonen
- Transaksjoner
- us
- Brukere
- verdi
- Vault
- synlighet
- Sikkerhetsproblemer
- sårbarhet
- Sårbar
- uke
- HVEM
- innenfor
- år