Escaneo de contratos de Ethereum en vivo en busca de un error de envío sin marcar. Parte 2

Continuación del artículo "Escaneo de contratos de Ethereum en vivo para el error de envío no verificado". Parte 1 " .


Hace casi un año (mientras Ethereum estaba en su lanzamiento "fronterizo"), el popular contrato de lotería EtherPot [9] también sufrió el mismo error. Una versión anterior de BTCRelay también mostró este error [7] . Aunque se detectó un peligro en una auditoría de seguridad anterior, primero se aplicó una corrección incorrecta [8] .


Detección de errores de envío no verificado en blockhain en vivo


¿Qué tan comunes son estos errores? ¿Escuchan las advertencias? ¿Se aplican las mejores prácticas? Respondemos estas preguntas empíricamente analizando los datos de la cadena de bloques Ethereum y el repositorio de códigos de Solidez que se encuentra en etherscrape.com. Para hacer esto, estamos desarrollando una herramienta de análisis de programa simple que verifica el contrato de cadena de bloques y utiliza la heurística para verificar si se utiliza uno de los métodos de protección más efectivos. El Listado 2 muestra la primera técnica de seguridad, como se recomienda en la documentación de Ethereum, que debe verificar el valor de retorno de enviar y lanzar una excepción. Para detectar el uso de este método, usamos una aproximación aproximada: solo miramos si el valor de retorno de enviar se ignora o no.

El Listado 4 ilustra la segunda técnica de seguridad recomendada en el manual de UMD, que verifica directamente si la pila de llamadas está llena enviando un mensaje de prueba. Para descubrir esta técnica, nuevamente usamos una aproximación aproximada: solo verificamos si se está enviando un mensaje además del comando de envío .

Si ninguno de estos indicadores heurísticos está presente, concluimos que no se está siguiendo ninguna de las recomendaciones de mejores prácticas. Implementamos estas heurísticas mediante la coincidencia de patrones simples con el código de bytes EVM compilado. Puede encontrar más detalles sobre cómo hacemos esto en el Apéndice [12] .


¿Cuántos contratos son vulnerables?


Comencemos comprobando la heurística en el repositorio Etherscrape del código fuente de Solidity. A partir del 20 de marzo de 2016, el relé Etherscrape contenía 361 programas de contratos de Solidez, 56 de los cuales contenían una declaración de envío. De estos programas contractuales, suponemos que la mayoría (al menos 36 de 56) no utilizan ninguno de los métodos de programación defensivos.

Incluso si el contrato no utiliza ninguna de las tecnologías de protección, puede o no tener una vulnerabilidad real. Verificamos manualmente los contratos de Solidity para confirmar la vulnerabilidad. Para nuestros propósitos, consideramos que un contrato es vulnerable si su estado puede cambiar incluso si el comando de envío no funciona (por lo que veremos el código vulnerable en el Listado 5). Confirmamos que la gran mayoría de las vulnerabilidades están presentes, 32 de 36 de estos contratos.


Asimismo, nuestra heurística no garantiza la correcta aplicación de la programación defensiva. Tomemos, por ejemplo, WeiFund, un DApp descentralizado de código abierto de crowdfunding. Este contrato tiene dos funciones: reembolso () y pago () , que engañan a nuestra heurística. Lo siguiente es un extracto del reembolso .


function refund(uint _campaignID, uint contributionID) public { ... receiver.send(donation.amountContributed); donation.refunded = true; ... if(c.config != address(0)) WeiFundConfig(c.config).refund(_campaignID, donation.contributor, donation.amountContributed); } 

En este código, se envía un mensaje a WeiFundConfig (c.config) para invocar el método de reembolso, pero solo bajo ciertas condiciones. Si c.config es un valor nulo, entonces el contrato es realmente vulnerable a un ataque de pila de llamadas. Al marcar *, ninguno de los programas de Solidity que pasaron nuestras pruebas heurísticas realmente aplicó directamente la mejor práctica recomendada de prueba de pila de llamadas. * *

Luego dirigimos nuestra atención a los contratos redactados en la cadena de bloques Ethereum. Observamos la imagen del 20 de marzo de 2016 (marca de tiempo: 1184243). Esta instantánea contiene un total de 13645 cadenas de bloques, que aparentemente son generadas por el compilador Solidity, de las cuales solo 1618 (11.8%) incluyeron el comando de envío .

De estos, la gran mayoría no parece utilizar ninguna de las técnicas de programación defensiva.


¿Qué pasa con el problema de la carrera recursiva en TheDAO? El contrato inteligente más emocionante en estos días, TheDAO [11] , sufre un error completamente separado, que es que no es "seguro para su reutilización" [13] . Este es otro tipo de programación insegura (conectada, pero distinta), que también se esperaba en controles de seguridad anteriores [6] , pero, como antes, es probable que muchos contratos no sean seguros hoy en día. El trabajo futuro consistía en crear una herramienta que también pudiera detectar dicho error.


¿Dónde salió todo mal?


No esperamos que la programación de contratos inteligentes sea completamente simple, al menos por ahora. Sin embargo, es sorprendente que esta forma particular de error esté tan extendida, a pesar del hecho de que se describió hace mucho tiempo durante el desarrollo del ecosistema Ethereum.

Un informe de 2015 [6] hizo esta recomendación a los desarrolladores de Ethereum: "

Actualmente, los ejemplos de programación presentados en la documentación son insuficientes para difundir las mejores prácticas para redactar contratos seguros y resolver el problema del mecanismo de gas. Los tutoriales introductorios de C ++ a menudo se saltan
Comprobación de errores de legibilidad, lo que condujo a numerosos errores de seguridad. Los ejemplos de Ethereum deberían enseñar los mejores hábitos. Recomendación: proporcione aún más ejemplos de la programación cuidadosa de los contratos de seguridad ".

Solo conocemos una respuesta oficial a esta pregunta, que es agregar una advertencia a la documentación oficial de Solidez mencionada anteriormente [3], que se repite a continuación: "Existe algún peligro al usar enviar : la transmisión falla si la profundidad de la pila de llamadas 1024 (esto siempre puede ser llamado por la persona que llama), y también falla si el destinatario se queda sin gas, por lo que para garantizar una transmisión segura, siempre verifique el valor de retorno del envío o incluso mejor: use el patrón en el que el destinatario retira dinero ".


Creemos que esta observación no es suficiente para documentar el problema. Ofrece solo una mitigación incompleta y describe solo una versión del peligro, lo que puede inducir a error al lector sobre su grado.


  • Actualización:
    La insuficiencia de la documentación de Solidity también fue ilustrada en detalle por Peter Wesenes. [16]


Además, la advertencia parece ser a menudo pasada por alto. Por lo tanto, creemos que son necesarias medidas preventivas adicionales.



¿Cómo puede ayudar Etherscrape?


Creemos que el uso de herramientas de análisis estático, incluso las crudas, como las descritas en esta publicación, puede ayudar a mejorar la calidad de los contratos inteligentes. En Etherscrape, integramos herramientas de análisis como esta en nuestro servicio web público, y agregamos un enlace a la página de la herramienta. cuando ella estará lista. Esto facilitará la visualización del código de contrato inteligente al resaltar los lugares donde pueden ocurrir errores. Asumimos que los usuarios de un contrato tan inteligente (por ejemplo, los posibles inversores en TheDAO o sus ofertas) pueden usar fácilmente herramientas como el control de sanidad antes de depositar su dinero. Incluso los inversores no técnicos pueden responsabilizar a los desarrolladores por explicar cómo reaccionaron a los problemas señalados en el código.

Etherscrape también ayuda analizando la cadena de bloques pública y controlando la prevalencia de este error, lo que puede ayudar a decidir, por ejemplo, cuánto dinero se debe asignar para la investigación y el desarrollo de herramientas de análisis estático. Además, compiladores como solc pueden integrar dichos análisis, proporcionando una advertencia al programador cuando parece probable un error.


Lectura recomendada



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


All Articles