NewsDevelopersEnterpriseBlockchain ExplainedEvents and ConferencesPressButlletins informatius
Subscriu-te al nostre butlletí.
Correu electrònic
Respectem la vostra privadesa
IniciBlogBlockchain Development
Recomanacions sobre seguretat intel·ligent d’Ethereum
Des de com gestionar les trucades externes fins als esquemes de compromís, aquí teniu més de deu patrons de seguretat de contractes intel·ligents que cal seguir quan es construeixi a Ethereum. ConsenSys, 10 de juliol de 2020
Tal com tractàvem a la mentalitat de seguretat de contractes intel·ligents, un desenvolupador vigilant d’Ethereum sempre manté cinc principis bàsics:
- Prepareu-vos per al fracàs
- Llançament amb cura
- Mantingueu els contractes senzills
- Estigueu al dia
- Tingueu en compte la idiosincràsia de l’EVM
En aquesta publicació, ens endinsarem en la idiosincràsia de l’EVM i examinarem una llista de patrons que heu de seguir quan desenvolupeu qualsevol sistema de contractes intel·ligents a Ethereum. Aquesta peça és principalment per a desenvolupadors intermedis d’Ethereum. Si encara esteu en les primeres etapes de l’exploració, consulteu el programa per a desenvolupadors de blockchain a la carta de ConsenSys Academy.
D’acord, endinsem-nos.
Trucades externes
Tingueu precaució quan feu trucades externes
Les trucades a contractes intel·ligents no fiables poden introduir diversos riscos o errors inesperats. Les trucades externes poden executar codi maliciós en aquest contracte o en qualsevol altre contracte del qual depengui. Per tant, tracteu totes les trucades externes com un potencial risc de seguretat. Quan no sigui possible o no desitjat eliminar trucades externes, utilitzeu les recomanacions de la resta d’aquesta secció per minimitzar el perill.
Marqueu els contractes no fiables
Quan interactueu amb contractes externs, anomeneu les vostres variables, mètodes i interfícies contractuals de manera que quedi clar que interactuar amb ells és potencialment insegur. Això s’aplica a les vostres pròpies funcions que convoquen contractes externs.
// bad Bank.withdraw (100); // No es clar si la funció de confiança o no de confiança makeWithdrawal (quantitat uint) {// No està clar que aquesta funció sigui potencialment insegura Bank.withdraw (quantitat); } // bona UntrustedBank.withdraw (100); // trucada externa no confiable TrustedBank.withdraw (100); // contracte bancari extern, però de confiança, mantingut per la funció XYZ Corp makeUntrustedWithdrawal (uint import) {UntrustedBank.withdraw (import); } Llenguatge del codi: PHP (php)
Eviteu els canvis d’estat després de trucades externes
Tant si utilitzeu trucades en brut (del formulari someAddress.call ()) com trucades contractuals (del formulari ExternalContract.someMethod ()), suposem que es podria executar codi maliciós. Fins i tot si ExternalContract no és maliciós, es poden executar codis maliciosos mitjançant qualsevol contracte que truqui.
Un perill particular és que el codi maliciós pot segrestar el flux de control, cosa que provoca vulnerabilitats a causa de la seva reentrada. (Vegeu Reentrància per a una discussió més completa d’aquest problema).
Si feu una trucada a un contracte extern no fiable, eviteu els canvis d’estat després de la trucada. Aquest patró també es diu de vegades el patró de comprovacions-efectes-interaccions.
Veure SWC-107
No utilitzeu transferència () ni enviament ().
.transfer () i.enviar () reenviar exactament 2.300 gas al destinatari. L’objectiu d’aquest estipendi de gas codificat per la seguretat era prevenir vulnerabilitats de reentrada, però això només té sentit suposant que els costos del gas són constants. EIP 1884, que formava part de la bifurcació d’Istanbul, va augmentar el cost del gas de l’operació SLOAD. Això va provocar que la funció alternativa d’un contracte costés més de 2300 gasos. Recomanem deixar d’utilitzar.transfer () i.send () i, en canvi, use.call ().
// mal contracte Vulnerable {retirada de la funció (quantitat uint256) externa {// Això reenvia 2300 gasolina, que potser no n’hi haurà prou si el destinatari // és un contracte i els costos del gas canvien. msg.sender.transfer (quantitat); }} // bon contracte Fix {retirada de la funció (quantitat uint256) externa {// Això reenvia tot el gas disponible. Assegureu-vos de comprovar el valor de retorn. (èxit boolè,) = msg.sender.call.value (quantitat) (""); requerir (èxit, "La transferència ha fallat."); }} Idioma del codi: JavaScript (javascript)
Tingueu en compte que.call () no fa res per mitigar els atacs de reentrada, de manera que cal prendre altres precaucions. Per evitar atacs de reentrada, utilitzeu el fitxer patró de comprovacions-efectes-interaccions.
Tractar els errors de les trucades externes
Solidity ofereix mètodes de trucades de baix nivell que funcionen en adreces sense processar: address.call (), address.callcode (), address.delegatecall () i address.send (). Aquests mètodes de baix nivell no generen mai una excepció, però tornaran falsos si la trucada troba una excepció. D’altra banda, les trucades contractuals (per exemple, ExternalContract.doSomething ()) propagaran automàticament un llançament (per exemple, ExternalContract.doSomething () també es llançarà si llançaments doSomething ()).
Si decidiu utilitzar els mètodes de trucada de baix nivell, assegureu-vos de gestionar la possibilitat que la trucada falli comprovant el valor de retorn.
// dolent someAddress.send (55); someAddress.call.value (55) (""); // això és doblement perillós, ja que reenviarà tot el gas restant i no comprovarà el resultat someAddress.call.value (100) (bytes4 (sha3 ("dipòsit ()"))); // si el dipòsit genera una excepció, la trucada en brut () només retornarà falsa i la transacció NO es revertirà // bona (èxit boolè,) = someAddress.call.value (55) (""); if (! success) {// gestiona el codi de fallada} ExternalContract (someAddress) .deposit.value (100) (); Idioma del codi: JavaScript (javascript)
Veure SWC-104
Afavoreixi l’empenta per a trucades externes
Les trucades externes poden fallar accidentalment o deliberadament. Per minimitzar els danys causats per aquests errors, sovint és millor aïllar cada trucada externa en la seva pròpia transacció que pot iniciar el destinatari de la trucada. Això és especialment rellevant per als pagaments, on és millor deixar que els usuaris retirin fons en lloc d’invertir-los automàticament. (Això també redueix la possibilitat de problemes amb el límit de gas.) Eviteu combinar diverses transferències d’èter en una única transacció.
// subhasta de contracte dolent {adreça més altaBidder; uint maximumBid; funció oferta () a pagar {require (msg.value >= Oferta més alta); if (higherBidder! = address (0)) {(bool success,) = higherBidder.call.value (higherBid) (""); requerir (èxit); // si aquesta trucada falla constantment, ningú més no pot fer una oferta} higherBidder = msg.sender; majorBid = msg.value; }} // subhasta de bon contracte {adreça més altaBidder; uint maximumBid; mapatge (adreça => uint) reembossaments; funció oferta () a pagar externa {require (msg.value >= Oferta més alta); if (majorBidder! = adreça (0)) {reembossaments [majorBidder] + = majorBid; // registra el reembossament que aquest usuari pot reclamar} higherBidder = msg.sender; majorBid = msg.value; } function retireRefund () external {uint refund = refunds [msg.sender]; devolucions [msg.sender] = 0; (èxit boolè,) = msg.sender.call.value (reembossament) (""); requerir (èxit); }} Idioma del codi: JavaScript (javascript)
Veure SWC-128
No delegueu la trucada a codi no fiable
La funció de trucada delegada crida a funcions d’altres contractes com si pertanyessin al contracte de la persona que truca. Per tant, el destinatari pot canviar l’estat de l’adreça de trucada. Pot ser insegur. Un exemple següent mostra com utilitzar delegatecall pot provocar la destrucció del contracte i la pèrdua del seu equilibri.
contract Destructor {funció doWork () externa {selfdestruct (0); }} contract Worker {funció doWork (adreça _internalWorker) pública {// unsafe _internalWorker.delegatecall (bytes4 (keccak256 ("fer feina()"))); }} Idioma del codi: JavaScript (javascript)
Si es diu Worker.doWork () amb l’adreça del contracte de destructor desplegat com a argument, el contracte de treballador s’autodestruirà. Delegar l’execució només a contractes de confiança i mai a una adreça proporcionada per un usuari.
Advertiment
No suposeu que els contractes es creen amb saldo zero. Un atacant pot enviar èter a l’adreça d’un contracte abans de crear-lo. Els contractes no haurien de suposar que el seu estat inicial conté un saldo zero. Veure número 61 per a més detalls.
Veure SWC-112
Recordeu que l’èter es pot enviar per força a un compte
Compte amb la codificació d’un invariant que comprovi estrictament el saldo d’un contracte.
Un atacant pot enviar èter per força a qualsevol compte. Això no es pot evitar (ni tan sols amb una funció alternativa que reverteixi ()).
L’atacant pot fer-ho creant un contracte, finançant-lo amb 1 wei i invocant l’autodestructió (victimAddress). No s’invoca cap codi a victimAddress, de manera que no es pot evitar. Això també és cert per a la recompensa de blocs que s’envia a l’adreça del miner, que pot ser qualsevol adreça arbitrària.
A més, atès que es poden pre-computar les adreces del contracte, es pot enviar èter a una adreça abans que es desplegui el contracte.
Veure SWC-132
Recordeu que les dades de la cadena són públiques
Moltes sol·licituds requereixen que les dades enviades siguin privades fins a algun moment per funcionar. Jocs (per exemple, tisores de paper de cadena) i mecanismes de subhasta (per exemple, ofertes segellades) Subhastes Vickrey) són dues grans categories d’exemples. Si esteu creant una aplicació on la privadesa és un problema, assegureu-vos d’evitar que els usuaris publiquin informació massa d’hora. La millor estratègia és utilitzar-la esquemes de compromís amb fases separades: cometeu primer usant el hash dels valors i en una fase posterior revelant els valors.
Exemples:
- En les tisores de paper de roca, requereixen que tots dos jugadors presentin primer un hash de la seva jugada prevista i, a continuació, que ambdós jugadors presentin la seva jugada; si el moviment enviat no coincideix amb el hash, el llançarà.
- En una subhasta, requereu que els jugadors presentin un hash del seu valor d’oferta en una fase inicial (juntament amb un dipòsit superior al seu valor d’oferta) i, a continuació, envieu el valor de l’oferta de subhasta a la segona fase.
- Quan es desenvolupa una aplicació que depèn d’un generador de números aleatoris, l’ordre sempre ha de ser (1) els jugadors envien moviments, (2) es genera un número aleatori, (3) els jugadors es paguen. Molta gent investiga activament els generadors de nombres aleatoris; Les solucions més actuals de la categoria inclouen capçaleres de blocs Bitcoin (verificades a través de http://btcrelay.org), esquemes hash-commit-revelació (és a dir, una part genera un número, publica el seu hash per “comprometre” el valor i després revela el valor més endavant) i RANDAO. Atès que Ethereum és un protocol determinista, no podeu utilitzar cap variable dins del protocol com a número aleatori imprevisible. Tingueu en compte també que els miners controlen en certa mesura el valor block.blockhash ()*.
Compte amb la possibilitat que alguns participants puguin “caure fora de línia” i no tornar-hi
No depengueu els processos de reembossament ni de reclamació que una part concreta realitzi una acció concreta sense cap altra manera d’obtenir els fons. Per exemple, en un joc de paper de tisora, un error comú és no fer cap pagament fins que els dos jugadors presentin els seus moviments; no obstant això, un jugador malintencionat pot “entristir-se” a l’altre simplement sense presentar mai el seu moviment; de fet, si un jugador veu el moviment revelat de l’altre jugador i determina que ha perdut, no té cap raó per presentar el seu propi moviment. Aquest problema també pot sorgir en el context de la liquidació dels canals estatals. Quan aquestes situacions són un problema, (1) proporcionen una manera d’eludir els participants que no participen, potser mitjançant un límit de temps, i (2) consideren afegir un incentiu econòmic addicional perquè els participants presentin informació en totes les situacions en què es trobin. se suposa que ho hauria de fer.
Compte amb la negació del nombre enter signat més negatiu
Solidity proporciona diversos tipus per treballar amb enters signats. Com a la majoria de llenguatges de programació, a Solidity un enter signat amb N bits pot representar valors des de -2 ^ (N-1) fins a 2 ^ (N-1) -1. Això significa que no hi ha cap equivalent positiu per al MIN_INT. La negació s’implementa com a trobar el complement dels dos d’un nombre, de manera que la negació del nombre més negatiu donarà lloc al mateix nombre. Això és cert per a tots els tipus sencers signats de Solidity (int8, int16, …, int256).
contract Negation {function negate8 (int8 _i) rendiments públics purs (int8) {return -_i; } function negate16 (int16 _i) rendiments purs públics (int16) {return -_i; } int8 public a = negate8 (-128); // -128 int16 public b = negate16 (-128); // 128 int16 public c = negate16 (-32768); // -32768} Llenguatge del codi: PHP (php)
Una manera de gestionar-ho és comprovar el valor d’una variable abans de negar-la i llançar-la si és igual al MIN_INT. Una altra opció és assegurar-se que el nombre més negatiu no s’aconseguirà mai mitjançant l’ús d’un tipus amb una capacitat més elevada (per exemple, int32 en lloc d’int16).
Un problema similar amb els tipus int es produeix quan MIN_INT es multiplica o divideix per -1.
El vostre codi blockchain és segur?
Esperem que aquestes recomanacions hagin estat útils. Si vosaltres i el vostre equip us esteu preparant per al llançament o fins i tot al començament del cicle de vida del desenvolupament i necessiteu comprovar el seny dels vostres contractes intel·ligents, contacteu amb el nostre equip d’enginyers de seguretat de ConsenSys Diligence. Som aquí per ajudar-vos a llançar i mantenir les vostres aplicacions Ethereum amb una confiança del 100%.
Reserveu una comprovació de punts de seguretat
Reserveu una revisió d’un dia amb el nostre equip d’experts en seguretat de blockchain. Reserveu-vos avui Seguretat Contractes intel·ligents Butlletí d’informació Subscriviu-vos al nostre butlletí per obtenir les últimes novetats, solucions empresarials, recursos per a desenvolupadors i molt més sobre Ethereum. Adreça electrònica Contingut exclusiuSeminari web
Com es pot crear un producte Blockchain amb èxit
Seminari web
Com configurar i executar un node Ethereum
Seminari web
Com es crea la seva pròpia API Ethereum
Seminari web
Com es crea un testimoni social
Seminari web
Ús d’eines de seguretat en el desenvolupament de contractes intel·ligents
Seminari web