WEB3DEV Español

Cover image for Mala Aleatoriedad en Solidity
Delia Viloria T
Delia Viloria T

Posted on

Mala Aleatoriedad en Solidity

Image description

Introducción

Es fácil generar números azarosos en lenguajes de programación como JavaScript o Python, pero es más complicado hacerlo de forma segura en Solidity. Solidity necesita que el azar sea seguro para diferentes aplicaciones como juegos y loterías. La razón es que las blockchains son determinísticas, esto quiere decir que la salida de cualquier función siempre será la misma por la misma entrada. Esto hace que sea difícil generar números realmente azarosos en la blockchain, como cualquier algoritmo usado para generar azar que pueda ser explotado.

Este artículo cubrirá el rol de la aleatoriedad en Solidity, fuentes de mala aleatoriedad, cómo obtener aleatoriedad usando las funciones VRF del oráculo Chainlink, hackeos y técnicas de mitigación.

El Rol del Azar en Solidity

La aleatoriedad es un elemento importante en muchas aplicaciones Web3, incluyendo juegos en cadena, loterías y protocolos de finanzas descentralizadas (DeFi). Es usado para crear resultados impredecibles, los cuales pueden ser añadidos a las mecánicas de jugabilidad, asegurar la distribución justa de las recompensas y prevenir el fraude.

Por ejemplo: en un juego Web3, la aleatoriedad puede usarse para determinar el resultado de una batalla, el nivel de rareza de un objeto NFT o la distribución del botín. En una lotería, la aleatoriedad es usada para seleccionar los números ganadores. En los protocolos DeFi, la aleatoriedad puede usarse para generar claves privadas, las cuales son usadas para asegurar los fondos de los usuarios.

Cuando viene a la aleatoriedad, hay dos formas diferentes: pseudoaleatoriedad y verdadera aleatoriedad. La pseudoaleatoriedad es generado por algoritmos deterministas, mientras que la verdadera aleatoriedad recae en fuentes de entropía impredecibles e imparciales.

Los números pseudoaleatorios aparentan ser azarosos, pero son generados por una fórmula. Esto quiere decir que pueden predecirse si sabes la fórmula y el valor semilla inicial.

La verdadera aleatoriedad se genera por procesos físicos que son inherentemente impredecibles. La verdadera aleatoriedad se usa para aplicaciones de seguridad sensible, como la generación de claves criptográficas.

Mala Aleatoriedad

La vulnerabilidad de mala aleatoriedad ocurre cuando un contrato inteligente depende de una fuente de azar que no es realmente aleatoria o que puede ser predecida por un atacante. Esto puede permitir que un atacante manipule el resultado de una transacción o gane una ventaja injusta sobre otros usuarios.

Hay diferentes fuentes de mala aleatoriedad en los contratos inteligentes, y estaremos viendo algunos de ellos:

  • Usar el bloque del hash como una fuente de aleatoriedad:

Un bloque de hash es un valor que es derivado de los contenidos de un bloque en la blockchain Ethereum. Es considerado como pseudoaleatorio porque está basado en las transacciones y otros datos contenidos en el bloque, porque no es realmente azaroso porque es determinado por los contenidos del bloque, los cuales pueden ser conocidos o predecibles por un atacante.

  • Usar la estampilla de tiempo (timestamp) actual del bloque como fuente de aleatoriedad:

No se recomienda usar block.timestamp como fuente de aleatoriedad porque puede ser influenciado o manipulado por los validadores (mineros). Los validadores tienen cierto grado de control sobre el valor block.timestamp. Pueden ajustarse a la estampilla de tiempo de un bloque que minan, siempre cuando esté dentro de cierto rango de tolerancia. Esto quiere decir que los mineros pueden, potencialmente, manipular la estampilla de tiempo para generar resultados específicos en contratos inteligentes que dependen en block.timestamp para la aleatoriedad. En un alto nivel, puede suceder un ataque front-running.

  • Usar las variables locales y el almacenamiento como fuente de aleatoriedad:

Las variables locales y las variables de almacenamiento en Solidity, pueden usarse para generar valores azarosos o para tomar decisiones que deben ser impredecibles. Sin embargo, los valores de estas variables son visibles para todos los participantes en el contrato, haciendo que sea posible para actores malignos predecir o manipular los resultados

Hackeos Causados por Mala Aleatoriedad

Estaremos mirando un hackeo del mundo real que ocurrió por mala aleatoriedad en un contrato:

Hackeo Fomo3D

Fomo3D es un juego de lotería donde la última persona en comprar una clave, gana. Los jugadores pueden comprar claves durante una ronda y el precio de las claves se incrementa ligeramente con cada compra. Los jugadores también pueden ganar una entrada pasiva desde el juego mientras las claves se compran. Cuando la ronda termina, la última persona en comprar una clave gana el pote.

Lo que atrajo a las personas al juego fueron los airdrops. Los airdrops son premios que son dados a jugadores al azar. Esto también atrajo a atacantes.

Los ganadores son elegidos totalmente al azar. El contrato Fomo3D usa múltiples fuentes de aleatoriedad para generar números aleatorios como la creación del tiempo del bloque, la dirección del minero del bloque actual y la dirección del jugador actual, los cuales explicamos anteriormente que son malas fuentes de aleatoriedad.

Aquí está la fórmula usada:

contract FoMo3Dlong is modularLong {
   /**
    * @dev genera un número aleatorio entre 0-99 y revisa si
    * resultó en un airdrop, gana
    * @return ¿tenemos un ganador?
    */
   function airdrop()
       private
       view
       returns(bool)
   {
       uint256 seed = uint256(keccak256(abi.encodePacked(
           (block.timestamp).add
           (block.difficulty).add
           ((uint256(keccak256(abi.encodePacked(block.coinbase)))) / (now)).add
           (block.gaslimit).add
           ((uint256(keccak256(abi.encodePacked(msg.sender)))) / (now)).add
           (block.number)
       )));
       if((seed - ((seed / 1000) * 1000)) < airDropTracker_)
           return(true);
       else
           return(false);
   }
}
Enter fullscreen mode Exit fullscreen mode

Usando este método para determinar los ganadores al azar para el airdrop hace que el contrato de Fomo3D sea predecible y vulnerable al ataque.

El atacante realizó su ataque usando un contrato para engañar al contrato de Fomo3D que fue un EOA (porque sólo los EOA son elegibles para los airdrops y los no contratos) y también fue capaz de manipular la aleatoriedad del contrato inteligente de Fomo3D y obtener el airdrop, saliéndose con la suya con muchos ether.

Obtener Aleatoriedad usando Chainlink VRF

Chainlink es una red de oráculo descentralizado que proporciona fuentes de datos seguros y confiables y computación fuera de la cadena para los contratos inteligentes. Permite a los contratos inteligentes acceder a datos y eventos del mundo real, y realizar cálculos complejos fuera de la cadena, sin comprometer su seguridad.

Chainlink es usado por un gran rango de aplicaciones descentralizadas incluyendo: protocolos DeFi, plataformas de seguros y aplicaciones de juegos. Uno de los mayores servicios de Chainlink es VRF (verifiable random function, función azarosa verificable) en el cual, obtienes números azarosos.

Chainlink VRF es un generador de números azarosos (RNG, random number generator) probado como justo y verificable, que permite a los contratos inteligentes usar números al azar sin sacrificar la seguridad y usabilidad. Por cada pedido, Chainlink VRF produce uno o más números aleatorios y una prueba criptográfica de cómo fueron generados. La prueba se publica y verifica en la blockchain antes que cualquier aplicación pueda usarse. Este proceso asegura que nadie, incluyendo los operadores Oráculo, mineros, usuarios o los desarrolladores de contratos inteligentes, puedan manipularlo o manipular los resultados.

Los métodos de la suscripción y la financiación directa son dos métodos que puedes usar para generar números azarosos usando Chainlink VRF.

El método de suscripción es buena para pedidos regulares de aleatoriedad donde necesitas pedir aleatoriedad frecuentemente. Con este método creas una cuenta de suscripción con pre fondos con tokens LINK. Luego, cuando necesitas aleatoriedad, simplemente lo pides desde tu cuenta de suscripción. Los costos VRF son calculados luego que tus pedidos son completados y luego deducidos desde el balance de tu suscripción.

El método de fondos directos es bueno para pedidos aleatorios infrecuentes o peticiones únicas. Con este método, no necesitas crear una cuenta de suscripción. En vez, colocas los fondos directamente en el contrato con tokens LINK antes que pida la aleatoriedad. Los costos VRF son estimados y cobrados al momento del pedido.

La principal diferencia entre los dos métodos es que el método de suscripción es más eficiente para pedidos regulares mientras que el método de fondo directo es más eficiente para pedidos infrecuentes.

Chainlink proporcionó una guía simple sobre cómo usar ChainlinkV2 VRF para generar números aleatorios en tus contratos inteligentes en su documentación.

Técnicas de Mitigación

Para evitar usar mala aleatoriedad en Solidity, es importante implementar aleatoriedad segura en tus contratos inteligentes cuando construyes tus aplicaciones blockchain.

  • Usa Chainlink VRF: Chainlink VRF es una forma segura para generar números aleatorios en tus proyectos de contrato inteligente. Cuando quieres implementar aleatoriedad en tu contrato de Solidity, no uses datos de bloque relacionados a los datos, como los bloques de hashes, bloques de las estampillas de tiempo o bloques de números, para generar números azarosos porque pueden ser manipulados. Es recomendable integrar Chainlink VRF.
  • Mantén tu contrato inteligente al día con los últimos arreglos de seguridad y las mejores prácticas, y mantenla usualmente auditada para encontrar cualquier vulnerabilidad, especialmente aquellas relacionadas con la aleatoriedad.

Conclusión

La mala aleatoriedad es una falla de seguridad seria en los contratos de Solidity. Puede ser explotado por atacantes para manipular los resultados de contratos inteligentes, llevando a pérdidas financieras para los usuarios. Los desarrolladores deberían estar conscientes de esta vulnerabilidad y tomar pasos para mitigarlos como usar oráculos descentralizados que proporcionen funciones seguras de aleatoriedad como Chainlink VRF.

Este artículo fue escrito por Natachi Nnamaka y traducido por Delia Viloria T. Su original se puede leer aquí.

Sería genial escucharte en nuestro Discord, puedes contarnos tus ideas, comentarios, sugerencias y dejarnos saber lo que necesitas.
Si prefieres puedes escribirnos a @web3dev_eshttps://twitter.com/web3dev_es en Twitter.

Discussion (0)