We hebben zojuist gezien hoe een kleine maas in de wet leidt tot een financieel verlies (van verschillende omvang), op dezelfde manier waarop slimme contracten die via Solidity zijn ontwikkeld, vatbaar zijn voor verschillende bekende en onbekende aanvallen. De uitbuiters maken gebruik van bugs en mazen om in slimme contracten te gluren en deze te manipuleren om aanvallen uit te voeren. Hier presenteren we een uitgebreide lijst van de top 5 veelvoorkomende fouten in de programmeertaal Solidity.
Bij QuillAudits volgen we de adaptieve methodologie om de kern van elke hack te begrijpen en de lessen ervan te implementeren in toekomstige slimme contracten om mogelijke bedreigingen te voorkomen.
Fouten in solidity programmeertaal
1. Niet aangevinkt extern gesprek
We trekken dit probleem in de eerste plaats omdat het een van de meest waargenomen Solidity-valkuilen is. Over het algemeen wordt het verzenden van ether naar een extern account uitgevoerd via de overdracht() functie. Afgezien hiervan zijn de twee meest gebruikte functies om extern te bellen; bellen () en sturen(), hier vooral de bellen () functie wordt veelvuldig gebruikt om veelzijdige externe oproepen uit te voeren door de ontwikkelaars.
Hoewel de bellen () en sturen() functies retourneren een booleaanse waarde die aangeeft of de aanroep een succes was of niet. Dus in dit geval, als een van de functies bellen () or sturen() de taak niet uitvoert, zullen ze terugkeren met a vals. Dus als de ontwikkelaar de retourwaarde niet kruiselings controleert, zou het een valkuil worden.
De kwetsbaarheid
Beschouw het onderstaande voorbeeld:
contract Lotto{
boolpublic uitbetaald =false;
adres openbare winnaar;
uintpublic winBedrag;
// … extra functionaliteit hier
functie sendToWinner()public{
vereisen(!uitbetaald);
winnaar.send(winBedrag);
uitbetaald = waar;
}
functie terugtrekkenLeftOver()public{
vereisen (uitbetaald);
msg.afzender.send(dit.saldo);
}
}
In het Lotto-achtige contract hierboven kunnen we constateren dat a winnaar ontvangt winBedrag van ether waardoor er een beetje overgebleven is om te worden onttrokken aan een extern middel.
Hier bestaat de valkuil voor het contract op regel [11], waar a sturen wordt gebruikt zonder kruisvalidatie van het antwoord. In het bovenstaande voorbeeld, a winnaar wiens transactie mislukt (ofwel door een tekort aan Gas of als het een contract is dat opzettelijk in de fallback-functie gooit), autoriseert uitbetaald worden ingesteld op waar ongeacht of de transactie met ether een succes was of niet. In dit geval kan elke uitbuiter de winnaar's winst via de terugtrekkenLeftOver functie.
De aanpak van QuillAudit
Ons interne team van ontwikkelaars pakt deze bug aan met behulp van [overdracht] functie in plaats van [sturen] functie, aangezien [overdracht] zal terugkeren als externe transactie terugkeert. En als u [verzenden] gebruikt, controleer dan altijd de retourwaarde.
Een van de robuuste benaderingen die we volgen, is het gebruik van een [terugtrekkingspatroon]. Hier isoleren we logischerwijs de externe verzendfunctionaliteit van de rest van de codebase, en leggen we de belasting van mogelijk mislukte transacties op de eindgebruiker, aangezien hij degene is die de opnamefunctie aanroept.
2. Herintreding
De slimme contracten van Ethereum bellen en gebruiken codes van andere externe contracten, en om dit uit te voeren, moeten de contracten externe oproepen indienen. Deze externe oproepen zijn kwetsbaar en vatbaar voor aanvallen, een dergelijke aanval vond onlangs plaats in het geval van DAO-hack.
De kwetsbaarheid
Aanvallers voeren dergelijke aanvallen uit wanneer een contract ether naar een onbekend adres stuurt. In dit geval kan de aanvaller een contract maken op een extern adres dat kwaadaardige code bevat in de fallback-functie, en deze kwaadaardige code zal worden aangeroepen wanneer het contract ether naar dit adres stuurt.
Feit: De term 'Reentrancy' is ontstaan uit het feit dat wanneer een extern kwaadaardig contract een functie over het kwetsbare contract aanroept en het code-uitvoeringspad het vervolgens 'opnieuw binnengaat'.
Overweeg het onderstaande voorbeeld, het is een Ethereum-kluis waarmee deposanten slechts 1 ether per week kunnen opnemen.
contracteer EtherStore {
uint256 openbare terugtrekkingLimit = 1 ether;
mapping (adres => uint256) public lastWithdrawTime;
mapping(adres => uint256) openbare saldi;
functie depositFunds() extern betaalbaar {
saldi[msg.sender] += msg.value;
}
functie retractFunds (uint256 _weiToWithdraw) public {
vereisen (saldi[msg.sender] >= _weiToWithdraw);
// beperk de opname
vereisen(_weiToWithdraw <= opnamelimiet);
// beperk de tijd om je terug te trekken
vereisen (nu >= lastWithdrawTime[msg.sender] + 1 weken);
vereisen(msg.sender.call.value(_weiToWithdraw)());
saldi[msg.sender] -= _weiToWithdraw;
lastWithdrawTime[msg.sender] = nu;
}
}
In het bovenstaande contract hebben we twee publieke functies, [depositFunds] en [withdrawFunds]. De [depositFunds] wordt gebruikt om het saldo van de afzender te verhogen, terwijl [withdrawFunds] het op te nemen bedrag specificeert. In dit geval is het een succes als het op te nemen bedrag minder is dan 1 ether.
De valkuil ligt hier in lijn [17] waar de overdracht van ether plaatsvindt. De aanvaller kan een kwaadaardig contract maken met het contractadres van [EtherStores] als de enige constructorparameter. Dit zou van [etherStore] een openbare variabele maken, en dus vatbaarder voor aanvallen.
De aanpak van QuillAudit
We volgen verschillende technieken om potentiële herintredingskwetsbaarheden in slimme contracten te voorkomen. De allereerste en de best mogelijke manier is het gebruik van de ingebouwde [overdracht]-functie bij het overzetten van ether naar een extern contract.
Ten tweede is het belangrijk om ervoor te zorgen dat alle logische veranderingen in de toestandsvariabelen moeten worden gedaan voordat ether uit het contract wordt gestuurd. In het [EtherStore]-voorbeeld moeten regels [18] en [19] vóór regel [17] worden geplaatst.
Een derde techniek kan ook worden gebruikt om herintredende oproepen te voorkomen; door de introductie van een mutex. Het is een toevoeging van een toestandsvariabele die het contract vergrendelt tijdens het uitvoeren van de code.
3. Standaard zichtbaarheid
Er zijn zichtbaarheidsspecificaties voor de functies die we in Solidity gebruiken, en ze schrijven voor hoe ze kunnen worden aangeroepen. Het is de zichtbaarheid die het aanroepen van de functies bepaalt; extern door gebruikers, door andere afgeleide contracten, alleen intern of alleen extern. Laten we eens kijken hoe foutief gebruik van zichtbaarheidsspecificaties een enorme kwetsbaarheid in slimme contracten kan veroorzaken.
De kwetsbaarheid
Standaard is de zichtbaarheid van de functie [public], vandaar dat de externe gebruikers de functies kunnen aanroepen zonder specifieke zichtbaarheid. De bug doet zich voor wanneer ontwikkelaars vergeten zichtbaarheid te specificeren op functies die privé moeten zijn (of binnen het contract zelf kunnen worden aangeroepen). Bijvoorbeeld;
contracteer HashForEther {
functie terugtrekkenWinnings() {
// Winnaar als de laatste 8 hexadecimale tekens van het adres 0 zijn
vereisen (uint32(msg.sender) == 0);
_sendWinningen();
}
functie _sendWinnings() {
msg.afzender.overdracht (dit.saldo);
}
}
Het bovenstaande contract is een eenvoudig premiespel voor het raden van een adres. Hierin kunnen we zien dat de zichtbaarheid van de functies niet is gespecificeerd, met name de functie [ _sendWinnings] is [public] (standaard), vandaar dat dit via elk adres kan worden aangeroepen om de premie te stelen.
De aanpak van QuillAudit
Ons interne team bestaat uit doorgewinterde ontwikkelaars die altijd de beste auditpraktijken volgen, hier moet de zichtbaarheid van de functies expliciet worden gespecificeerd, zelfs als ze openbaar moeten worden gehouden, moet dit worden vermeld.
4. Bescherming van het gebruik van constructeurs
Over het algemeen worden Constructors speciale functies genoemd die worden gebruikt om kritieke en bevoorrechte taken uit te voeren tijdens het initialiseren van de contracten. Vóór Solidity [v0.4.22] hadden constructeurs dezelfde naam die werd gebruikt door het contract waarin ze waren opgenomen. Overweeg nu een geval waarin de contractnaam tijdens de ontwikkelingsfase wordt gewijzigd, maar de naam van de constructor hetzelfde blijft. Deze maas in de wet kan aanvallers ook gemakkelijk toegang geven tot uw slimme contract.
De kwetsbaarheid
Het kan ernstige gevolgen hebben als de contractnaam wordt gewijzigd, maar de naam van de constructor ongewijzigd blijft. Bijvoorbeeld:
contract EigenaarWallet {
adres openbare eigenaar;
// constructeur
functie ownerWallet(adres _owner) public {
eigenaar = _eigenaar;
}
// Terugvallen. Verzamel ether.
functie () betaalbaar {}
functie terugtrekken() openbaar {
vereisen (msg.sender == eigenaar);
msg.afzender.overdracht (dit.saldo);
}
}
In het bovenstaande contract kunnen we zien dat alleen de eigenaar ether kan intrekken door de functie [opnemen] aan te roepen. Hier treedt de kwetsbaarheid op omdat de constructor anders wordt genoemd dan het contract (de eerste letter is anders!). Dus de uitbuiter kan de [ownerWallet]-functie aanroepen en zichzelf autoriseren als eigenaar, en vervolgens alle ether in het contract intrekken door [intrekken].
De aanpak van QuillAudit
Wij voldoen aan versie [0.4.22] van de Solidity compiler. Deze versie heeft een trefwoord geïntroduceerd; [constructor] die vereist dat de naam van de functie overeenkomt met de contractnaam.
5. Tx.Origin-authenticatie
Hier is [Tx.Origin] de globale variabele van Solidity, het bevat het adres van de rekening die de aanroep of transactie oorspronkelijk heeft uitgevoerd. Deze variabele kan niet worden gebruikt voor authenticatie, omdat dit het contract kwetsbaar maakt voor phishing-aanvallen.
De kwetsbaarheid
Contracten die gebruikers autoriseren via de variabele [tx.origin] worden blootgesteld aan externe aanvallen waardoor gebruikers geauthenticeerde acties uitvoeren op het foutieve contract. Beschouw het onderstaande voorbeeld:
contract Phishable {
adres openbare eigenaar;
constructor (adres _eigenaar) {
eigenaar = _eigenaar;
}
functie () extern te betalen {} // collect ether
functie terugtrekkenAlle(adres _ontvanger) openbaar {
vereisen (tx.origin == eigenaar);
_ontvanger.overboeking (dit.saldo);
}
}
Hier op regel [11] autoriseert het contract de functie [withdrawAll] met behulp van [tx.origin].
De aanpak van QuillAudit
Over het algemeen vermijden we het gebruik van [tx.origin] voor autorisatie in slimme contracten. Hoewel het gebruik van [tx.origin] niet strikt verboden is, kent het enkele specifieke gebruikssituaties. We kunnen [tx.origin] gebruiken om te voorkomen dat externe contracten het huidige contract aanroepen, het kan worden uitgevoerd met [require] van de vorm [require(tx.origin == msg.sender)]. Het wordt gedaan om te voorkomen dat tussentijdse contracten worden opgeroepen om het huidige contract op te roepen, waardoor het contract wordt beperkt tot reguliere adressen zonder code.
Laatste afronding
We hebben de vijf veelvoorkomende valkuilen in de Solidity-taal uitgebreid behandeld. Bij het ontwikkelen van slimme contracten mogen we niet vergeten dat ze onveranderlijk zijn qua ontwerp, wat betekent dat als we ze eenmaal hebben gemaakt, er geen manier is om de broncode te patchen.
Dit vormt een grote uitdaging voor ontwikkelaars om te profiteren van de beschikbare tools voor beveiligingstests en audits voordat ze worden geïmplementeerd.
Het ontdekken van potentiële kwaadaardige bedreigingen voor de slimme contracten en de risico's waarvan sommige hierboven zijn genoemd, worden op een zeer unieke en robuuste manier uitgevoerd door ons interne team van auditexperts. Wij bij QuillAudits doen ons uiterste best voor beveiligingsonderzoek om uw contract up-to-date te houden met alle softwarebeveiligingspraktijken om uw contract veilig te houden.
Neem contact op met QuillHash
Met een jarenlange aanwezigheid in de branche QuillHash heeft wereldwijd bedrijfsoplossingen geleverd. QuillHash met een team van experts is een toonaangevend blockchain-ontwikkelingsbedrijf dat verschillende industrieoplossingen biedt, waaronder DeFi-onderneming.Als u hulp nodig heeft bij de audit van slimme contracten, neem dan gerust contact op met onze experts hier!
Volg QuillHash voor meer updates
Bron: https://blog.quillhash.com/2021/06/04/top-5-common-errors-in-solidity-programming-language/
- 11
- Account
- Voordeel
- Alles
- controleren
- authenticatie
- machtiging
- BEST
- blockchain
- Bug
- bugs
- Bellen
- gevallen
- Veroorzaken
- uitdagen
- code
- Gemeen
- afstand
- contract
- contracten
- Actueel
- DAO
- Defi
- Design
- Ontwikkelaar
- ontwikkelaars
- Ontwikkeling
- Enterprise
- Ether
- ethereum
- Event
- deskundigen
- financieel
- Voornaam*
- volgen
- formulier
- Gratis
- functie
- toekomst
- spel
- GAS
- Globaal
- groot
- houwen
- hier
- Hoe
- HTTPS
- reusachtig
- Inclusief
- -industrie
- IT
- taal
- leiden
- leidend
- Lijn
- Lijst
- Match
- Overige
- eigenaar
- Patch
- Patronen
- Phishing
- phishing-aanvallen
- voorschrijven
- presenteren
- privaat
- Programming
- publiek
- trekken
- onderzoek
- antwoord
- REST
- veilig
- veiligheid
- Diensten
- reeks
- Eenvoudig
- Klein
- slim
- slim contract
- Slimme contracten
- So
- Software
- stevigheid
- Oplossingen
- Land
- succes
- Testen
- De Bron
- bedreigingen
- niet de tijd of
- top
- top 5
- transactie
- Transacties
- us
- gebruikers
- waarde
- Gewelf
- zichtbaarheid
- kwetsbaarheden
- kwetsbaarheid
- Kwetsbaar
- week
- WIE
- binnen
- jaar