Vulnerabilidades de EOS Blockchain en ZeroNights 2018

imagen

Este artículo analizará varias vulnerabilidades reales en la cadena de bloques EOS (uno de los competidores de Ethereum) y cómo se integraron en el concurso de máquinas tragamonedas seguras de nueva generación en ZeroNights 2018. Si está interesado en conocer cómo está la situación de seguridad esta red blockchain, entonces bienvenido bajo cat.

Entrada


Todo comenzó con el hecho de que recientemente, durante una auditoría de los contratos inteligentes de Etherium para seguridad, uno de nuestros amigos nos lanza un artículo sobre vulnerabilidades en los contratos inteligentes en la red EOS. Esto nos interesó mucho y decidimos investigar las vulnerabilidades con más detalle.

Todo esto finalmente llevó a la creación de una competencia para ZeroNights 2018 llamada "Bandido de un solo brazo" con vulnerabilidades en un contrato inteligente.

Comencemos directamente mirando la red blockchain de EOS, cómo trabajar con ella y cómo se organiza todo dentro de ella. Hay muchos artículos que describen la tecnología en Internet, por lo que lo más probable es que no haya detalles técnicos, pero trataremos de transmitir el significado general para que el usuario promedio pueda tener una idea elemental de los mecanismos de trabajo de la cadena de bloques EOS.

Descripción de la tecnología EOS


EOS.io es una cadena de bloques de nueva generación de Block.one , basada en el concepto de PoS ( Prueba de participación ).

Según la descripción de los propios creadores de la red: "EOS es un software de red blockchain de código abierto que proporciona a los desarrolladores y empresarios una plataforma para crear, implementar y ejecutar aplicaciones descentralizadas de alto rendimiento (DAPP)".

Si, en pocas palabras, trata de explicar el concepto, entonces está bien reflejado un extracto del artículo de Wikipedia:
La idea de la prueba de participación (PoS) es resolver el problema de la prueba de trabajo (PoW) asociada con un alto consumo de energía. En lugar del poder de cómputo de los participantes, la cantidad de criptomonedas que tienen en su cuenta es importante. Entonces, en lugar de usar una gran cantidad de electricidad para resolver el problema de PoW, el participante de PoS tiene un porcentaje limitado de posibles controles de transacciones. El límite corresponde a la cantidad de criptomoneda en la cuenta del participante.
La red es completamente nueva, y el primer lanzamiento de la red principal (mainnet) tuvo lugar el 10 de junio de 2018. La criptomoneda principal es EOS, y el portal principal para desarrolladores es developers.eos.io

La cadena de bloques EOS.io admite aplicaciones creadas por usuarios que utilizan el código WebAssembly (WASM), un nuevo estándar web con amplio soporte para grandes empresas como Google, Microsoft, Apple y otras.

Por el momento, el kit de herramientas más reciente para crear aplicaciones que compilan código en WASM es clang / llvm con su compilador C / C ++.

Para una mejor compatibilidad, los desarrolladores recomiendan usar EOSIO CDT (Contract Development Toolkit), un conjunto de utilidades de los propios desarrolladores para un trabajo conveniente y correcto en la creación de contratos inteligentes.

El compilador anterior de eosiocpp ya está en desuso y no es compatible, por lo que se recomienda a todos actualizar al nuevo (en el momento de la redacción) EOSIO CDT 1.5.

A diferencia del éter


Ether en su concepto usa PoW (Prueba de trabajo), que requiere cálculos costosos y la recompensa se le da a la primera persona para resolver un problema matemático. Es decir, aquellos que decidieron en paralelo, pero no tuvieron tiempo para decidir, desperdiciaron energía. En esta situación, los mineros están luchando entre ellos por tecnologías y equipos más avanzados. Para generar bloques más rápido y así ganar.

A diferencia de Ether en la red EOS, el sistema elegirá al creador del nuevo bloque de acuerdo con el concepto de PoS, y esto está determinado por el número de estado personal, una fracción de la criptomoneda total. Por lo tanto, quien tiene más fortuna tiene una mejor oportunidad de ser seleccionado por el sistema. Pero a diferencia de PoW (ether), en principio no hay recompensa por generar un nuevo bloque, y el ingreso de los mineros es únicamente la comisión de las transacciones.

Conclusión: las criptomonedas basadas en PoW pueden ser 1000 veces más eficientes energéticamente.

Desarrollamos el entorno de desarrollo.


Entonces, parece que hemos terminado la teoría, pasamos a la práctica. Pero en la práctica, todo parece mucho más interesante. Con la documentación en el momento en que intentaban resolverlo en el verano y comenzar a hacer algo para ZeroNights 2018, todo estaba muy mal, y el portal de desarrollo principal tenía errores, estaba medio vacío y a veces ni siquiera funcionaba.

Las redes de prueba aún no se han lanzado realmente, por lo que tuve que implementar mi nodo. Por cierto, a diferencia de las opiniones en Internet, hacer que resulte no es tan difícil. Usando la documentación oficial, la lanzamos desde los docker developers.eos.io/eosio-nodeos/docs/docker-quickstart

Hablemos de las principales utilidades, programas para trabajar con la cadena de bloques EOS, con los que tuve que lidiar en el momento de trabajar en la competencia:

  • Nodeos : de hecho, el servicio del propio nodo EOSIO; Puede configurar y configurar varios complementos, por ejemplo CORS, historial y otros.
  • Cleos es una utilidad de consola para trabajar con un nodo, llamar a métodos de contrato e interactuar con una billetera, llaves y accesos. La herramienta más común cuando se trabaja con EOS.
  • Keosd es una billetera de consola, o más precisamente, un servicio de billetera, una tienda de claves privadas.
  • Eosio.cdt : Contract Development Toolkit, el llamado conjunto de herramientas de desarrollador para depurar y compilar contratos, generar archivos ABI y más.
  • Eos.js : biblioteca de la API de Javascript para un trabajo conveniente con el nodo y los contratos a través de la web, incrustados en el sitio.
  • Scatter es una billetera de escritorio para el almacenamiento seguro de las claves de su cuenta. Hay una biblioteca web scatter.js, que interactúa con la billetera de escritorio Scatter en los zócalos web y, por lo tanto, ayuda a trabajar con aplicaciones DAPP en el navegador.

¡Uff! .. Sí, hay muchos programas, comprenderlos tampoco es del todo fácil. Una descripción de todo esto merece una publicación separada y está más allá del alcance de este artículo. Pero imaginemos que instalamos un nodo en nuestro servidor e incluso aprendimos cómo usar métodos de contrato para llamar a métodos de contrato si tuviéramos uno.

Sí, lo más importante. Necesitamos esbozar el contrato inteligente en sí. Lo escribiremos en C ++ y, para hacer al menos algo sensato, tuve que leer mucha documentación.

Para comprender los contratos, dan un ejemplo de un contrato Hello en todas partes. El archivo principal es hello.cpp y el contrato completo se describe en él.

#include <eosiolib/eosio.hpp> using namespace eosio; class hello : public eosio::contract { public: using contract::contract; /// @abi action void hi( account_name user ) { print( "Hello, ", name{user} ); } }; EOSIO_ABI( hello, (hi) ) 

Si en pocas palabras trata de explicar, entonces aquí, todo es simple . Cargamos la biblioteca eosio.hpp, luego creamos la clase hello (también conocida como el contrato) y heredamos el contrato de la clase. Creamos el método void hi e ingresamos la variable de usuario de tipo account_name en los parámetros, también es uint64_t. En el método, imprima "Hola" y el nombre que especificamos cuando se llama al método. La última línea donde se encuentra EOSIO_ABI es una macro auxiliar que acepta nuestra clase y métodos públicos de esta clase, y también participa en la formación del archivo .abi, donde se indican todos los métodos públicos del contrato.

Explorando vulnerabilidades


Entonces, en el marco de ese artículo , se describieron varias vulnerabilidades, consideremos ahora con más detalle.

Desbordamiento numérico - Desbordamiento numérico


Cuando se llama al contrato, el nodo verifica el tipo del parámetro, y si los datos que estamos tratando de alimentar no encajan, entonces el nodo comenzará a maldecir y dicha indignación no pasará. PERO! Si dentro del contrato hay algún tipo de algoritmo para cambiar el número, la suma de números o, por ejemplo, la multiplicación, entonces el número puede cambiar ya dentro del contrato. Esto significa que puede especificar un número que el nodo se saltará, pero multiplica el contrato y el número irá más allá del tipo de datos válido, lo que provocará un desbordamiento.

¿Qué puede dar? Por ejemplo, hay una verificación para algún tipo de parámetro numérico, digamos int Número <0, y se sabe que int es un número con signo, y si el número se desborda, entonces el signo del número para valores grandes cambiará a negativo. Por lo tanto, la verificación se desbordará. Y aquí, por supuesto, todo depende de la importancia de esta verificación.

Por ejemplo, en el mismo artículo sobre vulnerabilidades, hay un caso real en el que los atacantes pudieron influir en el parámetro de equilibrio, engañando así al sistema. Los comentarios del código describen con más detalle el mecanismo de interacción con el contrato:

 //      typedef struct acnts { account_name name0; account_name name1; account_name name2; account_name name3; } account_names; //     (   1 EOS) //  ,     , //      «» void batchtransfer( symbol_name symbol, account_name from, account_names to, uint64_t balance ){ //    require_auth(from); //    account fromaccount; //      require_recipient(from); require_recipient(to.name0); require_recipient(to.name1); require_recipient(to.name2); require_recipient(to.name3); // ,       . //   is_balance_within_range   ( eosio_assert(is_balance_within_range(balance), "invalid balance"); // ,      «» //  , «» 1111111111111111  0,     eosio_assert(balance > 0, "must transfer positive balance"); //   amount    4 //     ,  amount   int64_t amount = balance * 4; //     from,    int itr = db_find_i64(_self, symbol, N(table), from); // ,    eosio_assert(itr >= 0, "wrong name"); //    fromaccount   db_get_i64(itr, &fromaccount, (account)); // ,       // ,    0.1 EOS //    ,    amount eosio_assert(fromaccount.balance >= amount, "overdrawn balance"); //   sub_balance(symbol, from, amount); //    4  add_balance(symbol, to.name0, balance); add_balance(symbol, to.name1, balance); add_balance(symbol, to.name2, balance); add_balance(symbol, to.name3, balance); } 

La piratería probablemente se llevó a cabo de la siguiente manera. El atacante creó previamente 4 cuentas y llamó directamente al método de transferencia por lotes , algo como esto:

 cleos push action contractname batchtransfer \'{"symbol ":"EOS", "from":”attacker”, "to":{ “name0”:”acc0”, “name1”:”acc1”, “name2”:”acc2”, “name3”:”acc3”}, "balance":"111111111111111111 EOS"}' -p attacker@active 


imagen

Haré una reserva de inmediato, esto es solo una suposición; cómo hicieron exactamente el hack - no lo sabemos, y si hay otras ideas sobre esto o información más precisa, escriba los comentarios.

Comprobación de autenticación


La falta de verificación del método de contrato require_auth () para la autorización del usuario conducirá al hecho de que cualquier persona que no tenga los derechos necesarios puede usar los métodos privilegiados del contrato, por ejemplo, retirar dinero del contrato.

Falta de verificación de invocación de método


Al enviar dinero a un contrato (EOS), puede indicar en una macro especial lo que sucederá a continuación y qué hacer. Digamos que cuando recibe dinero, se llamará a un cierto algoritmo, por ejemplo, para iniciar la ruleta u otra cosa, así como un cheque:

 if( code == self || code == N(eosio.token) || action == N(onerror) ) { \ TYPE thiscontract( self ); \ switch( action ) { \ EOSIO_API( TYPE, MEMBERS ) \ } } //    action == N(transfer) 

En esta verificación, no hay restricciones para llamar al método de transferencia, por lo que puede llamar al método de transferencia directamente, sin enviar dinero al contrato. Y esto significa comenzar el mecanismo con una ganancia adicional, sin gastar un centavo.

Competencia ZeroNights 2018


La idea del concurso nació por sí sola: dado que todo está conectado con juegos y tres vulnerabilidades, por lo tanto, haremos el juego en el mecanismo de contrato inteligente en la cadena de bloques EOS.io. El juego debe ser lo más simple posible, pero interesante.

Tragamonedas "Bandido de un solo brazo"! Las personas que anhelan el dinero fácil siempre me han sorprendido. Recuerde, no hay regalos en el mundo, o casi ninguno. Aquí, por cierto, está bastante allí, o más bien, aparecerá cuando se utilicen vulnerabilidades.

Frontend


Decidieron hacer que los juegos de front-end fueran modernos, hermosos y tridimensionales. Gracias vtornik23 por no haberse negado a participar y ayudarnos a hacer una interfaz completa en el motor de Unity3d.

imagen

Máquina de juego tridimensional "bandido armado"; enviando 1 EOS y tirando de una palanca inteligente, ¡el jugador tiene la oportunidad de iniciar la rueda de la fortuna y ganar el premio gordo!

Vulnerabilidades contractuales


Según la idea del juego, se consideraba que la victoria era la pérdida de tres muñecas ZeroNights, que en el coeficiente numérico serían 777 o 0. Las posibilidades de ganar se igualaron al 0.02%, y algunos programadores desatentos trataron de complicar el algoritmo aleatorio agregando solo un desbordamiento de multiplicación. la cantidad de dinero enviada, y demasiado flojo para pensar en las condiciones con más detalle, así que simplemente escribí if (resultado == 777 || resultado <1), lo que hace posible deslizar un valor negativo.

  int rnd = random(999); int result = rnd * price.amount; uint64_t prize = 0; print("Result:", result); // BINGO 777 or 000 !!! ~ 0.02% if(result == 777 || result < 1 ) { prize = 100; sendtokens(from); } 

El contrato inteligente en sí se presenta en el github , para que todos puedan verlo de cerca desde todos los lados e identificar otras vulnerabilidades. Ya se han escrito sobre ellos un poco más arriba, por lo que no debería haber ninguna dificultad para encontrarlos.

Reglas para participar


Las reglas de participación son muy simples: era necesario tratar de ganar o piratear los mecanismos del sistema. Cuando se caen 3 matryoshkas - ¡Jackpot! El sistema carga 100 unidades de criptomoneda. Si un participante recibe un premio mayor 3 veces seguidas, se convierte en un ganador y recibe premios de los organizadores: sudaderas con capucha de marca, insignias, una variedad de artículos.

Por supuesto, podría ganar tirando de la palanca durante mucho tiempo y esperando suerte, pero la fortuna es impredecible y el porcentaje de ganancias es muy pequeño, por lo que fue más fácil de hackear.

Resultados de la competencia


Como resultado, la competencia, en nuestra opinión, fue perfecta. Se planearon recompensas para 3 personas, y solo tres lograron hacer frente a la competencia antes de la fecha de finalización programada. La competencia se llevó a cabo durante 2 días, durante los cuales los participantes tuvieron que resolver la tarea. El premio oficial y la presentación de obsequios se realizó al cierre de la conferencia en el escenario principal de ZeroNights 2018.

El énfasis principal se puso en el conocimiento de la tecnología EOS blockchain, y dejamos un par de consejos, uno de los cuales nadie pudo encontrar. Dejaremos este acertijo para más tarde ...

Comentarios de los participantes


Alexey (1 lugar)
ZeroNights es una de mis conferencias favoritas, comenzando con la primera, en San Petersburgo no me he perdido ninguna. Seguro que siempre da entusiasmo durante seis meses, y allí en primavera PHDays :). Los últimos 3 años he estado haciendo desarrollo de blockchain. Este año, la cadena de bloques llegó a ZeroNights (en el pasado, parece que también estaba en la hackvest, pero lo extrañé). En primer lugar, después de registrarme para la conferencia, fui a ver qué y cómo había con blockchain. Pensé que sería algo así como PHDays, algún tipo de curva aleatoria o condición de carrera en el aire. Pero aquí estaba EOS, con quien conocí un poco en el primer hackathon EOS, pero no fue largo, y además, se perdieron todas las configuraciones para el desarrollo. El espíritu de lucha cayó, y fui a esperar a que comenzara la conferencia. Pero la curiosidad mejoró, después de todo, ¡qué tiene de malo la EOS!

Stanislav Povolotsky (2 lugar)
Para mí fue un concurso largo pero interesante. Y fue una gran oportunidad para conocer la arquitectura de la cadena de bloques EOS. El concurso comenzó con la sorpresa de que no podrás acceder a la red EOS (mainnet), solo por $$$. Después de indicar que el contrato se implementó en la red de prueba, registrarse en esta red, configurar la dispersión y ver el historial de transacciones para el contrato del juego, quedó claro de inmediato cómo engañar a la máquina tragamonedas (el autor del contrato hizo esto varias veces durante las pruebas). Pero la confianza de que es tan rápido y fácil administrar la competencia desapareció rápidamente tan pronto como la red no aprobó todas mis transacciones con parámetros idénticos a la transacción ganadora.

Irina (3er lugar)
Antes de participar en la competencia, presentó el trabajo de los contratos inteligentes solo en teoría, por lo que fue muy interesante "conocerlos en vivo", ver el código fuente, probar las herramientas (y una vez más asegurarse de que Python sea el mejor). La tarea resultó ser realmente muy emocionante. Gracias

Y en conclusión


No quiere decir que todos se las arreglaron fácilmente. Para alguien fueron 2 días difíciles, y solo al final los afortunados lograron ganar usando las deficiencias de cualquier cadena de bloques: si la información ingresó a la cadena de bloques, entonces es accesible para todos, y si alguien ya ha pirateado algo, entonces el otro puede verlo. el camino

Agradecemos a todos los participantes y a quienes ayudaron a organizar el concurso.
¡Nos vemos en ZeroNights 2019, te esperan nuevas aventuras!

Source: https://habr.com/ru/post/es433552/


All Articles