Blog de AuditOne
Auditoría de un contrato de Solidity: Episodio 1 — Ataque de reentrada

Los contratos inteligentes son códigos que se ejecutan automáticamente y constituyen la columna vertebral del ecosistema Web3. Los contratos inteligentes actúan como los pilares fundamentales del ecosistema Web3, equilibrando con precisión miles de millones en una red abierta. Hoy hablaremos del ataque de reentrada, una de las vulnerabilidades más comunes que afectan a los contratos inteligentes. Este es un buen punto de partida si quieres aprender sobre Solidity y cómo auditar contratos inteligentes. Este es el primer artículo de una serie dedicada a la auditoría de contratos inteligentes en Solidity. La serie abordará las vulnerabilidades y los recursos que utilizan los auditores de contratos inteligentes.

¿Qué es un ataque de reentrada? 

Un ataque de reentrada es una vulnerabilidad de un contrato inteligente en la que un contrato atacante se aprovecha de una laguna en un contrato víctima, retirando fondos de este de forma repetida hasta que el contrato víctima quiebra. Esta vulnerabilidad se produce cuando el contrato víctima no verifica a tiempo el nuevo saldo del contrato atacante. 

Los contratos inteligentes suelen interactuar llamándose unos a otros, y el contrato del atacante, en un ataque de reentrada, deposita inicialmente tokens en el contrato de la víctima y, a continuación, realiza una llamada de retirada. El contrato del atacante impide intencionadamente que el contrato de la víctima reciba tokens, lo que provoca una discrepancia y activa la función de reserva, que recibe Ether. El contrato del atacante incluye código manipulador que llama continuamente al contrato de la víctima, lo que hace que este envíe Ether repetidamente sin saberlo. Esto permite al atacante vaciar los fondos del contrato de la víctima hasta que se agoten.

CryptoCasino es una dApp que permite a los usuarios apostar con criptomonedas. El contrato inteligente que rige CryptoCasino presenta una vulnerabilidad que permite un ataque similar al de «reentrada». El contrato inteligente también permite a los usuarios retirar su saldo restante en cualquier momento. El contrato actualiza el saldo del usuario solo una vez que este finaliza su sesión de apuestas, en lugar de actualizarlo tras cada apuesta. Alice crea una cuenta en CryptoCasino y deposita 1 ETH en el saldo de su cuenta.

Durante su sesión de juego, Alice realiza una apuesta de 0,5 ETH y retira su depósito inicial antes de que el contrato inteligente actualice su saldo. El contrato inteligente vulnerable no verifica el saldo actualizado de Alice hasta el final de la sesión de juego, por lo que sigue creyendo que ella tiene el 1 ETH inicial en su cuenta. Alice aprovecha esta vulnerabilidad retirando su depósito inicial antes de que el contrato pueda ajustar su saldo en función de las apuestas que ha realizado. Mediante este ataque similar a la reentrada, Alice puede vaciar los fondos del CryptoCasino sin que los operadores se den cuenta.

Creación de un contrato inteligente «Normal» y otro «Attacker»

Ahora que hemos explicado a fondo el concepto de reentrancia tanto desde el punto de vista técnico como desde la perspectiva de la vida real, deberías entenderlo mejor. Para demostrar la reentrancia, vamos a crear un contrato y otro contrato de atacante. Pero antes de eso, empecemos por crear un banco hipotético.

Contrato inteligente de la víctima

‍Contrato inteligente del atacante

Recomendaciones para los ataques de reentrada

Protección contra la reentrada

Un mecanismo de protección contra la reentrada evita que se ejecuten varias funciones vitales al mismo tiempo. He aquí un ejemplo:

A continuación, puedes incluir el modificador en la función «withdraw» de la siguiente manera:

También puedes importar la implementación de OpenZepellin del «Re-entrancy guard».

Se recomienda esto porque los contratos de OpenZepellin ya han sido auditados y son seguros.

Comprobar el patrón de interacción de los efectos

Este patrón garantiza que, cuando se inicia una función, primero se compruebe si el usuario tiene derecho a recibir los fondos. Si el resultado es positivo, se ajusta el saldo y, en el último paso, se envían los fondos al usuario.

En lugar de que tu función de retirada tenga este aspecto:

Debería ser así:

Es fundamental actualizar tu estado lo antes posible tras configurar la comprobación de requisitos.

En conclusión 

Si se produce en un entorno real, un ataque de reentrada puede provocar una pérdida significativa de fondos. El uso de protecciones contra la reentrada en los contratos inteligentes y la comprobación de los patrones de interacción reducen el riesgo de estas vulnerabilidades. Las auditorías de contratos inteligentes, los programas de recompensas por errores y las revisiones son fundamentales en todas las fases del desarrollo, ya que aumentan el número de personas que buscan vulnerabilidades y reducen la probabilidad de que se pasen por alto vulnerabilidades críticas.

¡Mantente a salvo!

Únete a AuditOne como auditor: https://www.auditone.io/auditors
Reserva tu consulta gratuita sobre seguridad:

Google Calendar:
https://calendar.app.google/Ai15eyQhiV5c1pBXA
Telegram:
https://t.me/m_ndr


Artículos relacionados:

Auditoría de un contrato Solidity: Episodio 2 - Delegatecall

Auditoría de un contrato de Solidity: Episodio 3 - Análisis de seguridad

Auditoría de un contrato de Solidity: Episodio 4 — Pruebas

Auditoría de un contrato de Solidity: Episodio 5 - Herramientas de pruebas automatizadas

Auditoría de un contrato de Solidity: Episodio 6 - Frontrunning

Auditoría de un contrato de Solidity: Episodio 7 — Documentación y elaboración de informes

Auditoría de un contrato de Solidity: Episodio 8 - Ventajas de la auditoría

En este artículo
Autor
Ilustre Igwe
Triage de contratos inteligentes
¡Comparte esto con tu comunidad!
xtelegramlinkedin
Artículos recientes

¿Buscas más contenido interesante?

Descubre nuestra comunidad
Discord
x
Twitter
Medium
LinkedIn
YouTube