TON (The Open Network) es una plataforma blockchain descentralizada diseñada y desarrollada originalmente por el equipo de Telegram que llamó la atención tan pronto como se lanzó. El objetivo de TON es proporcionar una plataforma blockchain escalable y de alto rendimiento para admitir aplicaciones descentralizadas (DApps) y contratos inteligentes a gran escala. Los conocimientos básicos sobre TON se pueden encontrar en Conociendo TON: cuentas, tokens, transacciones y seguridad de activos.

Vale la pena señalar que TON tiene una arquitectura completamente diferente a la de otras cadenas de bloques. Además de utilizar principalmente el lenguaje FunC para la programación, los contratos inteligentes de TON también utilizan el Tact de nivel superior o el Fift de nivel inferior. Se trata de lenguajes muy originales, por lo que garantizar la seguridad de los contratos inteligentes es fundamental.

El equipo de seguridad de SlowMist integró y absorbió las prácticas de desarrollo de seguridad compartidas por la comunidad TON, combinadas con su propia experiencia en auditorías de seguridad acumuladas durante muchos años, para lanzar las "Mejores prácticas de seguridad de contratos inteligentes de Toncoin", con el objetivo de ayudar a los desarrolladores a comprender mejor la seguridad de Toncoin. contratos inteligentes y proporcionar soluciones prácticas para mitigar posibles amenazas a la seguridad.

Debido a limitaciones de espacio, este artículo solo enumera parte de las "Mejores prácticas de seguridad de contratos inteligentes de Toncoin". Le invitamos a mirar, bifurcar y destacar en GitHub: https://github.com/slowmist/Toncoin-Smart-Contract-Security. -Mejores -Prácticas.

Errores comunes de los contratos inteligentes de Toncoin

1. Falta el modificador impuro

  • Gravedad: alta

  • Descripción: un atacante puede descubrir que la función "autorizar" no está marcada como "impura". La ausencia de este modificador permitirá que el compilador omita llamar a una función si no tiene valor de retorno o si el valor de retorno no se utiliza.

  • Escenario de ataque:

  • Recomendación: asegúrese de que la función utilice el modificador "impuro".

2. Uso incorrecto de métodos de modificación/no modificación

  • Gravedad: Alta

  • Descripción: "udict_delete_get?" se llamó incorrectamente con "." en lugar de "~", por lo que no se modificó el diccionario real.

  • Escenario de ataque:

  • Recomendación: compruebe siempre si un método es un método modificable o no modificable.

3. Uso incorrecto de enteros con/sin signo

  • Gravedad: alta

  • Descripción: Los derechos de voto se almacenan en el mensaje como números enteros. Así, un atacante puede enviar valores negativos durante una transferencia de poder y obtener un poder de voto ilimitado.

  • Escenario de ataque:

  • Recomendación: en algunos escenarios, los enteros sin signo son más seguros porque pueden generar un error en caso de desbordamiento. Utilice números enteros con signo sólo cuando realmente los necesite.

4. Números aleatorios inseguros

  • Gravedad: Alta

  • Descripción: la semilla se deriva del tiempo lógico de la transacción y el atacante puede ganar mediante fuerza bruta descifrando el tiempo lógico en el bloque actual (porque el tiempo lógico es continuo dentro de los límites de un bloque).

  • Escenario de ataque:

  • Recomendación: siempre aleatorice la semilla antes de hacer "rand()", y preferiblemente nunca use números aleatorios en cadena, ya que el validador puede controlar o influir en la semilla.

5. Envíe datos privados en cadena

  • Gravedad: alta

  • Descripción: Recuerde, todos los datos se almacenarán en la cadena de bloques.

  • Escenario de ataque: la billetera está protegida con contraseña y su valor hash se almacena en los datos del contrato. Sin embargo, la cadena de bloques registra todo: la contraseña aparece en el historial de transacciones.

  • Recomendación: no envíe datos privados en cadena.

6. Faltan cheques para mensajes devueltos

  • Gravedad: alta

  • Descripción: Vault no devolvió un mensaje de controlador o proxy a la base de datos cuando el usuario envió una solicitud de "verificación". Podemos establecer "msg_addr_none" como la dirección de recompensa en la base de datos porque "load_msg_address" lo permite. Solicitamos una verificación de Vault y la base de datos intentó analizar "msg_addr_none" usando "parse_std_addr", pero el análisis falló. El mensaje fue devuelto desde la base de datos al almacén y la operación no fue "op_not_winner".

  • Escenario de ataque: Vault contiene el siguiente código en el controlador de mensajes de la base de datos:

  • Recomendación: revise siempre los mensajes devueltos, no se olvide de los errores causados ​​por funciones estándar, haga que sus condiciones sean lo más estrictas posible.

7. Riesgo de destrucción de cuenta en condiciones competitivas

8. Evite ejecutar código de terceros

  • Gravedad: Alta

  • Descripción: Los desarrolladores no tienen forma de ejecutar de forma segura código de terceros en los contratos porque CATCH no puede manejar una cantidad insuficiente de gas y un atacante solo necesita enviar cualquier estado del contrato y provocar una cantidad insuficiente de gas para lograr el ataque.

  • Escenario de ataque:

  • Recomendación: Evite ejecutar código de terceros en sus contratos.

9. Conflicto de nombres

  • Gravedad: Media

  • Descripción: Las variables y funciones Func pueden contener casi cualquier carácter legal.

  • Escenario de ataque: "var++", "~bits", "foo-bar+baz" y coma "," son nombres válidos de variables y funciones.

  • Recomendación: al escribir y verificar el código Func, debe utilizar herramientas linter.

10. Comprueba el valor del tiro.

  • Gravedad: Media

  • Descripción: Cada vez que la ejecución de TVM se detiene normalmente, se detiene con el código de salida "0" o "1". Aunque se realiza automáticamente, la ejecución de TVM puede interrumpirse de formas inesperadas si los comandos "throw(0)" o "throw(1)" arrojan directamente los códigos de salida "0" y "1".

  • Escenario de ataque:

  • Sugerencia: no utilice "0" o "1" como valor de lanzamiento.

11. Leer/escribir el tipo correcto de datos

  • Gravedad: Media

  • Descripción: Leer el valor de una variable inesperada y llamar a un método en un tipo de datos que no debería tener dicho método (o cuyo valor de retorno no está almacenado correctamente) es un error y no se omitirá como una "advertencia" o "notificación". ", En cambio, el código no se puede recuperar.

  • Escenario de ataque: tenga en cuenta que almacenar un valor inesperado puede estar bien, pero leerlo puede causar problemas. Por ejemplo, para variables enteras, se puede generar el código de error 5 (Entero fuera del rango esperado).

  • Recomendación: siga de cerca el funcionamiento de su código y sus posibles valores de retorno. Recuerde, al compilador sólo le importa el código y su estado inicial.

12. El código del contrato se puede actualizar.

  • Gravedad: Media

  • Descripción: TON implementa completamente el modelo Actor, lo que significa que el código del contrato se puede cambiar. El código se puede cambiar permanentemente mediante la instrucción TVM "SETCODE" o configurando el registro de código TVM en un nuevo valor unitario en tiempo de ejecución hasta el final de la ejecución.

  • Escenario de ataque: un desarrollador sin escrúpulos puede actualizar maliciosamente el código para robar fondos.

  • Recomendación: tenga en cuenta que el código del contrato se puede actualizar, asegúrese de que cualquier actualización siga prácticas seguras y utilice mecanismos como un modelo de gobernanza o aprobación de firmas múltiples para realizar cambios.

13. Transacciones y Etapas

  • Gravedad: Media

  • Descripción: La fase de cálculo ejecuta el código del contrato inteligente y luego realiza operaciones (como enviar mensajes, modificar código, cambiar bibliotecas, etc.). A diferencia de las blockchains basadas en Ethereum, si espera que el envío de un mensaje falle, no verá el código de salida de la fase de cálculo, porque el mensaje no se ejecuta en la fase de cálculo, sino en una fase de operación posterior.

  • Escenario de ataque: comportamiento inesperado cuando un mensaje falla durante la fase de operación, lo que lleva a suposiciones incorrectas sobre el estado de la transacción.

  • Recomendación: Entender que cada transacción consta de hasta cinco fases: fase de almacenamiento, fase de crédito, fase de cálculo, fase de operación y fase de rebote.

14. No se pueden extraer datos de otros contratos.

  • Gravedad: Media

  • Descripción: Los contratos en la cadena de bloques pueden residir en diferentes fragmentos y ser procesados ​​por diferentes validadores. Por lo tanto, los desarrolladores no pueden extraer datos de otros contratos bajo demanda. La comunicación es asíncrona y se produce mediante el envío de mensajes.

  • Escenario de ataque:

  • Recomendación: Diseñe una lógica de contrato en torno a mensajes asincrónicos y evite suposiciones sobre la disponibilidad de datos sincrónicos.

15. Dos ID de método predefinidos

  • Gravedad: Media

  • Descripción: Hay dos ID de método predefinidos: uno para recibir mensajes dentro de la cadena de bloques "(0)", generalmente llamado "recv_internal", y el otro para recibir mensajes desde el exterior "(-1)", llamado "recv_external".

  • Escenario de ataque:

  • Recomendación: utilice métodos como "force_chain(to_address)" para verificar que la dirección esté en la cadena correcta.

16. Utilice mensajes rebotables

  • Gravedad: alta

  • Descripción: La cadena de bloques TON es asíncrona y los mensajes no tienen que llegar en orden. Los mensajes de error deben manejarse correctamente.

  • Escenario de ataque:

  • Recomendación: utilice siempre mensajes rebotables ("0x18") para manejar adecuadamente los errores de mensajes.

17. Protección de repetición

  • Gravedad: Alta

  • Descripción: implemente protección de repetición para billeteras (contratos que almacenan fondos de los usuarios), ya sea usando números de secuencia ("seqno") para garantizar que los mensajes no se procesen dos veces o usando identificadores de transacción únicos con vencimiento.

  • Escenario de ataque:

  • Recomendación: utilice métodos de protección de reproducción, como números de secuencia o identificadores únicos de mensajes, para evitar ataques de reproducción.

18. Condiciones de carrera para mensajes

  • Gravedad: alta

  • Descripción: las cascadas de mensajes se pueden procesar en varios bloques y un atacante podría iniciar un flujo paralelo, provocando una condición de carrera.

  • Escenario de ataque: un atacante puede utilizar diferencias horarias para manipular el comportamiento del contrato.

  • Recomendación: Evite condiciones de carrera validando el estado en cada paso y no asumiendo coherencia de estado en el flujo de mensajes.

19. Usar el modo de valor transportado

  • Gravedad: Alta

  • Descripción: En transferencias de tokens (por ejemplo, TON Jetton), los saldos deben transferirse utilizando el modo de valor de acarreo. El remitente resta el saldo y el receptor lo suma o lo devuelve.

  • Escenario de ataque: si no se maneja adecuadamente, las balanzas Jetton pueden manipularse.

  • Recomendación: utilice el modo de valor transportado para garantizar una transferencia de valor correcta.

20. Tenga cuidado al reembolsar los costos excesivos de combustible

  • Gravedad: alta

  • Descripción: Si las tarifas de gas excedentes no se devuelven al remitente, es posible que los fondos se acumulen en el contrato con el tiempo. En principio, esto no es terrible, pero es un enfoque subóptimo. Se podría agregar una función para eliminar el exceso de tarifas, pero los contratos populares como TON Jetton aún devolverán mensajes de exceso de tarifas "op::excesses" al remitente.

21. Verifique el valor de retorno de la función

  • Gravedad: alta

  • Descripción: Las funciones siempre devuelven un valor o un error. Si ignora la verificación del valor de retorno, puede provocar un error lógico fatal.

  • Escenario de ataque:

  • Recomendación: compruebe siempre el valor de retorno de una función.

22. Compruebe si hay tokens Jetton falsos

  • Gravedad: alta

  • Descripción: El token Jetton consta de dos partes: "jetton-minter" y "jetton-wallet". Si el contrato de la bóveda no se valida correctamente, un atacante podría drenar los fondos de la bóveda depositando tokens falsos y retirando tokens valiosos.

  • Escenario de ataque:

  • Recomendación: verifique si el remitente está enviando tokens Jetton falsos calculando la dirección de la billetera Jetton del usuario.

escribe al final

Para los desarrolladores, seguir estas mejores prácticas puede mejorar eficazmente la seguridad de los contratos inteligentes y reducir los posibles riesgos de seguridad. Hoy en día, con el rápido desarrollo de la tecnología blockchain, la seguridad es siempre la máxima prioridad. Se espera que esta mejor práctica pueda ayudar a más desarrolladores a crear contratos inteligentes seguros y confiables y promover el desarrollo saludable de la tecnología blockchain.

Enlaces de referencia:

[1] https://dev.to/dvlkv/drawing-conclusions-from-ton-hack-challenge-1aep

[2] https://docs.ton.org/develop/smart-contracts/security/ton-hack-challenge-1

[3] https://docs.ton.org/learn/tvm-instructions/tvm-overview

[4] https://docs.ton.org/develop/smart-contracts/messages

[5] https://docs.ton.org/develop/smart-contracts/security/secure-programming

[6] https://docs.ton.org/develop/smart-contracts/security/things-to-focus

Autor |

Editora |

Composición tipográfica |