Skip to main content
Xcapit
Blog
·13 min de lectura·Fernando BoieroFernando Boiero·CTO & Co-Fundador

Seguridad de Smart Contracts: 10 Vulnerabilidades Comunes y Como Prevenirlas

blockchaincybersecuritysmart-contracts

Desde el hack de The DAO en 2016, las vulnerabilidades de smart contracts le han costado a la industria blockchain mas de USD 8 mil millones en fondos robados o congelados. La naturaleza inmutable de blockchain significa que una vez que un contrato defectuoso se despliega, no puede ser parcheado: el codigo es ley, bugs y todo. Cada vulnerabilidad que llega a mainnet es un exploit potencial esperando a suceder, y los atacantes son sofisticados, bien financiados e implacables.

Mapa del panorama de vulnerabilidades de smart contracts
Vulnerabilidades comunes de smart contracts: desde ataques de reentrada hasta manipulación de oráculos

Entender los patrones de vulnerabilidad mas comunes es la primera linea de defensa. Esta guia cubre diez vulnerabilidades criticas de smart contracts, explica como funciona cada una y provee estrategias concretas de prevencion que los equipos de desarrollo deberian implementar antes de que cualquier codigo llegue a produccion.

1. Ataques de Reentrancia

La reentrancia es la vulnerabilidad de smart contracts mas infame, responsable del hack original de The DAO que llevo al hard fork de Ethereum. Ocurre cuando un contrato hace una llamada externa a otro contrato antes de actualizar su propio estado. El contrato llamado puede entonces volver a llamar a la funcion original antes de que la primera ejecucion se complete, creando un loop recursivo que drena fondos mas alla de lo que deberia permitirse.

El ejemplo clasico es una funcion de retiro que envia ETH a un usuario antes de establecer su saldo en cero. Un atacante despliega un contrato con una funcion fallback que llama a withdraw nuevamente cuando recibe ETH. El resultado es que el atacante puede retirar su saldo multiples veces antes de que el contrato registre la deduccion.

Los ataques de reentrancia modernos han evolucionado mas alla del patron de funcion unica. La reentrancia cross-function explota estado compartido entre diferentes funciones en el mismo contrato. La reentrancia cross-contract apunta a estado compartido entre multiples contratos en un protocolo. La reentrancia de solo lectura manipula funciones view de las que contratos externos dependen para calculos de precios o colateral.

  • Segui el patron checks-effects-interactions: valida condiciones, actualiza estado, despues hace llamadas externas, nunca al reves
  • Usa guardas de reentrancia (mutex locks) en todas las funciones que cambian estado y hacen llamadas externas
  • Audita reentrancia cross-function y cross-contract, no solo patrones de funcion unica
  • Considera vectores de reentrancia de solo lectura si tu contrato expone funciones view usadas por otros protocolos
  • Usa patrones pull-over-push de pago donde los usuarios retiran fondos en lugar de que el contrato los envie

2. Overflow y Underflow de Enteros

El overflow de enteros ocurre cuando una operacion aritmetica produce un valor mayor que el maximo que un tipo de variable puede contener, causando que se reinicie a cero o un numero pequeno. El underflow de enteros es lo inverso: restar de cero se reinicia al valor maximo. En contratos financieros, esto puede significar que un usuario con cero tokens repentinamente tenga miles de millones, o un saldo enorme se vuelva insignificante.

Antes de Solidity 0.8.0, las operaciones aritmeticas no verificaban overflow o underflow por defecto, haciendo de esta una de las clases de vulnerabilidad mas comunes. El exploit del token BEC en 2018 uso un overflow de enteros para generar miles de millones de tokens de la nada, colapsando el valor del token a cero.

Aunque Solidity 0.8+ incluye verificaciones de overflow integradas, el peligro no ha desaparecido. El bloque unchecked deshabilita explicitamente estas protecciones para optimizacion de gas. Ademas, el casting de tipos entre diferentes tamanos de enteros (uint256 a uint128, por ejemplo) puede truncar valores silenciosamente. Y los protocolos escritos en otros lenguajes como Vyper o Rust tienen sus propios comportamientos de overflow.

  • Usa Solidity 0.8.0 o posterior para beneficiarte de las verificaciones de overflow y underflow integradas
  • Audita cada uso de la keyword unchecked para confirmar que el overflow es verdaderamente imposible en ese contexto
  • Se cuidadoso con el casting de tipos: valida explicitamente que los valores caben en el tipo destino antes de castear
  • Usa SafeMath o librerias equivalentes para contratos que deben soportar versiones anteriores de Solidity
  • Testea condiciones de borde: que pasa en cero, en valores maximos y en limites de tipo

3. Front-Running y Ataques MEV

El front-running ocurre cuando un atacante ve una transaccion pendiente en el mempool y envia su propia transaccion con un precio de gas mas alto para ejecutar primero. En blockchains publicas, todas las transacciones pendientes son visibles antes de incluirse en un bloque, creando una asimetria de informacion que actores sofisticados explotan para obtener ganancias. Esto es parte del fenomeno mas amplio de Maximal Extractable Value (MEV).

El patron de front-running mas comun en DeFi es el ataque sandwich. Un atacante ve un swap grande pendiente en un exchange descentralizado, compra el token objetivo primero (empujando el precio hacia arriba), deja que la transaccion de la victima se ejecute al precio inflado, y luego vende inmediatamente despues para obtener ganancia. La victima obtiene menos tokens de lo esperado, y el atacante se queda con la diferencia.

El front-running tambien afecta lanzamientos de tokens, mints de NFT, liquidaciones, actualizaciones de oraculos y votos de gobernanza. Cualquier transaccion donde el resultado depende del orden de ejecucion es potencialmente vulnerable.

  • Implementa proteccion de slippage con impacto de precio maximo aceptable definido por el usuario en todas las funciones de swap
  • Usa esquemas commit-reveal para operaciones donde el contenido de la transaccion debe estar oculto hasta la ejecucion
  • Considera el envio de transacciones privadas via Flashbots Protect o servicios similares de proteccion MEV
  • Disena mecanismos que sean independientes del orden donde sea posible: subastas por lotes en lugar de primero en llegar, primero en servir
  • Establece plazos razonables en las transacciones para evitar que sean retenidas y ejecutadas en momentos desventajosos
  • Para gobernanza, usa propuestas con time-lock con votacion por snapshot para prevenir manipulacion de votos con flash loans

4. Manipulacion de Oraculos

Los oraculos proporcionan datos externos a smart contracts, mas comunmente feeds de precios para protocolos DeFi. Si un atacante puede manipular los datos de precio de los que depende un contrato, puede enganar al protocolo para que tome decisiones basadas en informacion falsa. Este es uno de los vectores de ataque mas devastadores financieramente, responsable de cientos de millones en perdidas.

La tecnica mas comun de manipulacion de oraculos usa flash loans para distorsionar temporalmente precios on-chain. Un atacante pide prestado una cantidad masiva de tokens, los usa para mover el precio en un DEX, activa un protocolo vulnerable que lee ese precio del DEX, y luego se beneficia de la operacion con precio incorrecto, todo en una sola transaccion. Porque los flash loans no requieren colateral, el atacante no arriesga nada.

Incluso los proveedores de oraculos bien conocidos no son inmunes. Los feeds de Chainlink pueden tener datos obsoletos si las condiciones de actualizacion no se cumplen. Los oraculos TWAP de Uniswap pueden ser manipulados con capital sostenido durante multiples bloques. Las implementaciones personalizadas de oraculos frecuentemente tienen riesgos de centralizacion o retrasos en las actualizaciones que crean ventanas de explotacion.

  • Usa precios promediados ponderados por tiempo (TWAP) en lugar de precios spot para resistir manipulacion de un solo bloque
  • Implementa verificaciones de desviacion de precio que rechacen actualizaciones mas alla de un umbral razonable
  • Usa multiples fuentes de oraculos independientes con un mecanismo de mediana o consenso
  • Agrega verificaciones de frescura: rechaza datos de precio mas antiguos que un umbral definido
  • Implementa circuit breakers que pasen operaciones durante volatilidad extrema del mercado
  • Nunca uses un unico pool de DEX como tu fuente de precio exclusiva para operaciones financieras criticas

5. Fallas de Control de Acceso

Las vulnerabilidades de control de acceso ocurren cuando funciones criticas carecen de verificaciones de permisos adecuadas, permitiendo a usuarios no autorizados ejecutar operaciones privilegiadas. Esto incluye funciones de inicializacion desprotegidas, verificaciones de roles faltantes en operaciones de administracion, y transferencias de ownership mal implementadas. El hack de la wallet multi-sig de Parity, que congelo mas de USD 150 millones en ETH, fue causado por una funcion de inicializacion desprotegida que cualquiera podia llamar.

El peligro se amplifica por la naturaleza publica de blockchain. Cada funcion en un contrato es visible y llamable por cualquiera a menos que se restrinja explicitamente. A diferencia del software tradicional donde el servidor controla el acceso, los smart contracts deben aplicar sus propios permisos enteramente a traves de codigo. No hay firewall, no hay segmentacion de red y no hay validacion del lado del servidor, solo lo que el contrato mismo verifica.

Los patrones de proxy introducen complejidad adicional de control de acceso. El admin del proxy, el owner de la implementacion y la autoridad de upgrade pueden ser roles diferentes, y la confusion entre ellos crea vulnerabilidades. Los patrones de proxy transparente ayudan separando llamadas de admin de llamadas de usuario, pero la mala configuracion sigue siendo una fuente comun de bugs.

  • Usa librerias establecidas como AccessControl u Ownable de OpenZeppelin para gestion de permisos
  • Implementa el principio de minimo privilegio: cada rol deberia tener solo los permisos que necesita
  • Usa transferencias de ownership de dos pasos (proponer y aceptar) para prevenir transferencias accidentales a direcciones incorrectas
  • Agrega time-locks a cambios de parametros criticos para que la comunidad pueda revisar y reaccionar antes de que los cambios surtan efecto
  • Requeri aprobacion multi-firma para operaciones de administracion: nunca uses un unico EOA para gobernanza del protocolo
  • Audita patrones de proxy cuidadosamente, especialmente la relacion entre el admin del proxy y el owner de la implementacion

6. Ataques de Flash Loans

Los flash loans permiten a cualquiera pedir prestado una cantidad ilimitada de tokens con cero colateral, siempre que el prestamo sea devuelto dentro de la misma transaccion. Aunque son una innovacion legotima de DeFi para arbitraje y refinanciamiento, se han convertido en el mecanismo de financiamiento principal para exploits sofisticados. Los flash loans efectivamente le dan a cada atacante el capital de una ballena, eliminando la barrera financiera para ejecutar ataques de manipulacion de mercado.

Un ataque tipico de flash loan combina multiples vulnerabilidades en una sola transaccion atomica. El atacante pide prestados millones de dolares en tokens, los usa para manipular un oraculo de precios, explota un protocolo que depende de ese oraculo, extrae ganancias, devuelve el prestamo con interes, y se queda con la diferencia. Si cualquier paso falla, toda la transaccion se revierte y el atacante pierde solo la tarifa de gas.

Los ataques de flash loan son particularmente peligrosos porque son libres de riesgo para el atacante y pueden ser ejecutados por cualquiera con el conocimiento tecnico para construir la transaccion. El exploit de Euler Finance en 2023 uso un flash loan para manipular precios de colateral, resultando en una perdida de USD 197 millones, el mayor ataque de flash loan hasta la fecha.

  • Disena protocolos para ser resistentes a flash loans asumiendo que cualquier usuario podria tener capital ilimitado en una sola transaccion
  • Usa oraculos TWAP y promedios de precio multi-bloque que no puedan ser manipulados dentro de una sola transaccion
  • Implementa periodos minimos de bloqueo para depositos antes de que puedan usarse como colateral o poder de voto
  • Agrega restricciones de operacion en el mismo bloque: preveni deposito y prestamo en la misma transaccion donde sea apropiado
  • Testea tu protocolo con herramientas de simulacion de flash loan para identificar vectores de ataque potenciales
  • Considera si los invariantes de tu protocolo se mantienen cuando un usuario tiene capital temporal ilimitado

7. Denegacion de Servicio (DoS)

La denegacion de servicio en smart contracts ocurre cuando un atacante puede impedir que usuarios legitimos interactuen con un contrato. A diferencia de los ataques DoS web tradicionales que abruman servidores con trafico, los DoS de smart contracts explotan fallas logicas que bloquean funciones criticas permanente o temporalmente.

El patron mas comun es el DoS por loop ilimitado. Si un contrato itera sobre un array que crece sin limite, como una lista de holders de tokens para distribucion de dividendos, un atacante puede agregar suficientes entradas para que el costo de gas de la iteracion exceda el limite de gas del bloque. La funcion se vuelve permanentemente inllamable, y cualquier fondo bloqueado detras de ella se vuelve inaccesible.

Otro vector comun es el DoS por revert inesperado. Si un contrato envia ETH a una lista de direcciones y una de esas direcciones es un contrato que revierte al recibir, toda la operacion por lotes falla. Un atacante puede explotar esto para bloquear liquidaciones de subastas, conteo de votos de gobernanza, o cualquier operacion que deba procesar una lista de direcciones.

  • Evita loops ilimitados: usa patrones de paginacion o establece limites duros en los tamanos de arrays
  • Preferi patrones pull-over-push de pago: deja que los usuarios retiren en lugar de enviarles pagos
  • No hagas que operaciones criticas dependan de que llamadas externas sean exitosas: maneja las fallas con gracia
  • Usa llamadas externas con gas limitado (call con stipend) para prevenir que contratos llamados consuman todo el gas
  • Implementa mecanismos de recuperacion de emergencia que puedan sortear funciones bloqueadas cuando sea necesario
  • Testea con escenarios adversarios: que pasa si un participante actua maliciosamente?

8. Bugs de Logica en la Logica de Negocio

Los bugs de logica son vulnerabilidades donde el codigo hace exactamente lo que fue escrito para hacer, pero lo que fue escrito no es lo que los desarrolladores tenian la intencion. Estos son los bugs mas dificiles de detectar porque las herramientas automatizadas buscan patrones de vulnerabilidad conocidos, mientras que los bugs de logica son unicos para las reglas de negocio especificas de cada protocolo.

Ejemplos comunes incluyen calculos de tarifas incorrectos que permiten a los usuarios evitar pagar tarifas bajo condiciones especificas, formulas de distribucion de recompensas que pueden ser manipuladas depositando y retirando en momentos estrategicos, y mecanismos de liquidacion que no contemplan casos limite en ratios de colateral. El incidente de gobernanza de Compound Finance, donde un bug en la logica de distribucion de recompensas causo que USD 90 millones en tokens se distribuyeran incorrectamente, fue un puro bug de logica: el codigo se ejecuto impecablemente, pero la formula estaba mal.

Las vulnerabilidades de logica de negocio se amplifican por la composabilidad. Cuando tu protocolo interactua con otros protocolos, el comportamiento combinado puede producir resultados que ninguno de los protocolos anticipo. Un protocolo de prestamos y un agregador de rendimiento podrian ser seguros individualmente, pero su interaccion crea un loop de retroalimentacion explotable.

  • Escrihi especificaciones completas antes de codificar: documenta cada formula, cada caso limite y cada suposicion
  • Implementa testing basado en propiedades que verifica que los invariantes se mantienen en miles de escenarios aleatorios
  • Usa verificacion formal para propiedades matematicas criticas como conservacion de tokens y solvencia
  • Testea con escenarios economicos realistas, no solo tests unitarios: simula condiciones de estres del mercado
  • Que expertos en el dominio (no solo investigadores de seguridad) revisen la logica de negocio contra la especificacion
  • Documenta todas las suposiciones del protocolo explicitamente y testea que pasa cuando esas suposiciones se violan

9. Ataques de Replay de Firmas

El replay de firmas ocurre cuando un mensaje firmado valido puede ser reutilizado en un contexto donde no deberia ser aceptado. Si un contrato acepta una autorizacion firmada para transferir tokens pero no rastrea que firmas han sido usadas, la misma firma puede ser enviada multiples veces para drenar el saldo completo del usuario. Replicar firmas entre cadenas es otra variante: una firma valida en Ethereum puede ser replicada en Polygon o BSC si el contrato no incluye datos especificos de la cadena en el mensaje firmado.

Esta vulnerabilidad aparece frecuentemente en sistemas de meta-transacciones, transacciones sin gas, order books off-chain, y cualquier sistema que use firma de datos tipados EIP-712. La funcion permit (EIP-2612) es una implementacion comun que permite aprobaciones de tokens via firmas en lugar de transacciones on-chain, y es un objetivo comun para ataques de replay cuando se implementa incorrectamente.

El riesgo se eleva despues de forks de cadena. Cuando Ethereum transiciono a proof-of-stake y la cadena fork de proof-of-work continuo como ETHW, las firmas creadas en una cadena eran validas en ambas. Los protocolos que no incluian el chain ID en sus datos firmados eran vulnerables a replay cross-chain.

  • Incluye un nonce en cada mensaje firmado y rastrea los nonces usados on-chain para prevenir reutilizacion
  • Incluye el chain ID (EIP-155) en todos los datos firmados para prevenir replay cross-chain
  • Incluye la direccion del contrato en los datos firmados para prevenir replay entre diferentes instancias del contrato
  • Segui EIP-712 para firma de datos estructurados tipados: incluye separadores de dominio que previenen la mayoria de los vectores de replay
  • Implementa expiracion de firmas con deadlines para limitar la ventana de replay potencial
  • Despues de forks de cadena, audita todas las funciones basadas en firmas para vulnerabilidad de replay cross-chain

10. Storage No Inicializado y Problemas de Proxy

Las vulnerabilidades de storage no inicializado ocurren cuando las variables de contrato no se configuran apropiadamente durante el despliegue o la inicializacion, dejandolas con valores por defecto (cero para enteros, vacio para direcciones) que crean condiciones explotables. Esto es especialmente peligroso con patrones de proxy, donde el constructor del contrato de implementacion nunca se llama: el proxy llama a una funcion de inicializacion en su lugar, y si esa funcion puede ser llamada por cualquiera, un atacante puede tomar ownership del contrato.

El ataque de proxy no inicializado de mayor perfil ocurrio contra el contrato de implementacion de Wormhole en 2022. El equipo habia dejado el contrato de implementacion sin inicializar, permitiendo a un atacante llamar la funcion de inicializacion, tomar ownership y actualizar el contrato a una version maliciosa, resultando en una perdida de USD 320 millones.

La colision de storage es un riesgo relacionado en patrones de proxy. Si el proxy y los contratos de implementacion usan los mismos slots de storage para diferentes variables, escribir en uno corrompe al otro. El estandar EIP-1967 define slots de storage especificos para las direcciones del admin del proxy y la implementacion para evitar esto, pero las implementaciones de proxy personalizadas frecuentemente lo hacen mal.

  • Siempre llama al inicializador en la misma transaccion que el despliegue del proxy para prevenir front-running
  • Usa el modifier initializer de OpenZeppelin para asegurar que las funciones de inicializacion solo puedan llamarse una vez
  • Deshabilita inicializadores en el constructor del contrato de implementacion para prevenir ataques de inicializacion directa
  • Segui las convenciones de slots de storage de EIP-1967 para patrones de proxy para evitar colisiones de storage
  • Verifica que todas las variables de estado tengan valores iniciales sensatos: nunca asumas que el valor por defecto cero es seguro
  • Audita los caminos de upgrade cuidadosamente: asegurate de que las nuevas versiones de implementacion no introduzcan conflictos de layout de storage

Construyendo un Proceso de Desarrollo con Seguridad Primero

Prevenir vulnerabilidades no se trata solo de conocer los patrones: requiere una cultura de desarrollo y un proceso que haga de la seguridad una preocupacion de primera clase en cada etapa.

  • Escrihi una especificacion detallada antes de escribir codigo, incluyendo todos los casos limite, suposiciones economicas y modos de falla
  • Usa librerias establecidas y auditadas como OpenZeppelin en lugar de implementar patrones estandar desde cero
  • Implementa suites de testing completas: tests unitarios para funciones individuales, tests de integracion para interacciones cross-contract, y fuzz tests para condiciones de borde
  • Ejecuta herramientas de analisis de seguridad automatizadas (Slither, Mythril, Echidna) como parte de tu pipeline CI/CD, no solo antes de auditorias
  • Conduce revisiones de seguridad internas con un checklist cubriendo las diez categorias de vulnerabilidad de esta guia
  • Usa verificacion formal para invariantes matematicos criticos como conservacion de tokens y ratios de colateral
  • Despliega en testnets y ejecuta periodos de testing extendidos con monitoreo antes del despliegue en mainnet
  • Implementa upgradeability o circuit breakers que te permitan responder a vulnerabilidades descubiertas
  • Establece un programa de bug bounty con recompensas significativas proporcionales al valor que tus contratos protegen
  • Monitorea tus contratos post-despliegue con alertas automatizadas para patrones de transaccion inusuales

Cuando Obtener una Auditoria Profesional

Una auditoria de seguridad profesional deberia considerarse obligatoria para cualquier contrato que va a manejar valor significativo. Pero no todas las auditorias son iguales, y el timing importa. Auditar demasiado temprano, antes de que el codigo este estable, desperdicia dinero ya que los hallazgos se vuelven obsoletos con cada cambio. Auditar demasiado tarde, justo antes del lanzamiento, no deja tiempo para abordar apropiadamente los hallazgos.

El timing ideal es despues de que el codebase esta completo en funcionalidades, despues de que se han conducido revisiones internas y analisis automatizados, y con suficiente margen antes del lanzamiento para abordar hallazgos y obtener una re-revision. Planifica al menos 4-6 semanas para la auditoria inicial y 2-3 semanas para la re-revision de correcciones.

Al evaluar firmas de auditoria, busca equipos con experiencia especifica en el dominio de tu protocolo: DeFi lending, AMMs, bridges, marketplaces de NFT y sistemas de gobernanza cada uno tiene patrones de vulnerabilidad unicos. Las mejores firmas de auditoria combinan herramientas automatizadas, revision manual de codigo por multiples auditores independientes y modelado de ataques economicos.

Considera contratar multiples firmas de auditoria para protocolos de alto valor. Diferentes auditores tienen diferentes fortalezas y puntos ciegos, y una vulnerabilidad critica encontrada por el segundo auditor que el primero no detecto puede ahorrar millones.

La seguridad de smart contracts no es una actividad de una sola vez: es una disciplina continua que abarca todo el ciclo de vida del desarrollo. Las diez vulnerabilidades descritas en esta guia representan la mayoria de los fondos perdidos en exploits de blockchain, y cada una es prevenible con diseno, testing y revision adecuados.

Smart Contract Vulnerability Layers

En Xcapit, nuestro equipo de ciberseguridad combina expertise profundo en smart contracts con certificacion ISO 27001 y anos de experiencia en blockchain en produccion. Desde auditorias de seguridad y penetration testing hasta la construccion de procesos de desarrollo con seguridad primero, ayudamos a proyectos blockchain a proteger a sus usuarios y su reputacion. Conoce mas sobre nuestros servicios de ciberseguridad.

Share
Fernando Boiero

Fernando Boiero

CTO & Co-Fundador

Más de 20 años en la industria tecnológica. Fundador y director de Blockchain Lab, profesor universitario y PMP certificado. Experto y líder de pensamiento en ciberseguridad, blockchain e inteligencia artificial.

Construyamos algo grande juntos

IA, blockchain y software a medida — pensado para tu negocio.

Contactanos

¿Construyendo sobre blockchain?

Tokenización, smart contracts, DeFi — lo hemos implementado todo.

Artículos Relacionados

·11 min

Cómo Construir Pipelines DevSecOps para Proyectos Blockchain

Cómo diseñar e implementar un pipeline DevSecOps específico para desarrollo blockchain — análisis estático de smart contracts, pipelines de auditoría automatizadas, gestión de secretos, automatización de deployments y monitoreo post-deployment.