Anteriormente, el equipo de CertiK descubrió una serie de vulnerabilidades de denegación de servicio en la cadena de bloques de Sui. Entre estas vulnerabilidades, se destaca una nueva vulnerabilidad de alto impacto. Esta vulnerabilidad puede hacer que los nodos de la red Sui no puedan procesar nuevas transacciones y el efecto es equivalente a un apagado completo de toda la red.
El lunes pasado, CertiK recibió una recompensa por errores de $ 500,000 de SUI por descubrir esta importante vulnerabilidad de seguridad. CoinDesk, un medio autorizado en la industria de EE. UU., informó sobre el evento, y luego los principales medios también publicaron noticias relacionadas después de su informe.
Esta vulnerabilidad de seguridad se llama vívidamente "Rueda de hámster": su método de ataque único es diferente de los ataques conocidos actualmente. El atacante solo necesita enviar una carga útil de aproximadamente 100 bytes para activar un bucle infinito en el nodo de verificación de Sui, lo que hace que no responda. a nuevas transacciones.
Además, el daño causado por el ataque puede continuar después de que se reinicie la red y puede propagarse automáticamente en la red Sui, lo que hace que todos los nodos no puedan procesar nuevas transacciones como hámsters corriendo sin cesar en la rueda. Por lo tanto, nos referimos a este tipo único de ataque como un ataque de "rueda de hámster".
Después de descubrir el error, CertiK se lo informó a Sui a través del programa de recompensas por errores de Sui. Sui también respondió de manera efectiva la primera vez, confirmó la gravedad de la vulnerabilidad y tomó activamente las medidas correspondientes para reparar el problema antes del lanzamiento de la red principal. Además de reparar esta vulnerabilidad en particular, Sui también implementó mitigaciones preventivas para reducir el daño potencial que podría causar esta vulnerabilidad.
Para agradecer al equipo de CertiK por su divulgación responsable, Sui otorgó al equipo de CertiK una recompensa de $500,000.
Los detalles de esta vulnerabilidad crítica se divulgarán a nivel técnico a continuación, y se aclararán la causa raíz y el impacto potencial de la vulnerabilidad.
Explicación de vulnerabilidad
El papel clave de los validadores en Sui
Para cadenas de bloques basadas en el lenguaje Move, como Sui y Aptos, el mecanismo de protección para prevenir ataques maliciosos de carga útil es principalmente tecnología de verificación estática. A través de la tecnología de verificación estática, Sui puede verificar la validez de la carga enviada por el usuario antes de que se emita o actualice el contrato. El validador proporciona una serie de verificadores para garantizar la corrección de la estructura y la semántica. Solo después de pasar la verificación de verificación, el contrato ingresará a la máquina virtual Move para ser ejecutado.
Amenazas maliciosas de carga útil en la cadena de movimiento
La cadena Sui proporciona un nuevo conjunto de modelos de almacenamiento e interfaces además de la máquina virtual Move original, por lo que Sui tiene una versión personalizada de la máquina virtual Move. Para admitir nuevas primitivas de almacenamiento, Sui presenta además una serie de métodos de inspección adicionales y personalizados para la verificación de seguridad de las cargas útiles que no son de confianza, como la seguridad de objetos y las funciones de acceso al almacenamiento global. Estos cheques personalizados se ajustan a las características únicas de Sui, por lo que los llamamos validadores de Sui.
El orden de Sui de controlar las cargas.
Como se muestra en la figura anterior, la mayoría de las comprobaciones en el verificador realizan una verificación de seguridad estructural contra CompiledModule (que representa la ejecución de la carga útil del contrato proporcionada por el usuario). Por ejemplo, use el "Comprobador de duplicados" para asegurarse de que no haya entradas duplicadas en la carga útil del tiempo de ejecución; use el "Verificador de límites" para asegurarse de que la longitud de cada campo en la carga útil del tiempo de ejecución esté dentro del límite de entrada máximo permitido.
Además de las comprobaciones estructurales, las comprobaciones estáticas del verificador aún requieren métodos de análisis más complejos para garantizar la solidez de las cargas útiles no confiables a nivel semántico.
Más información sobre el intérprete abstracto de Move:
Análisis lineal e iterativo
El intérprete abstracto proporcionado por Move es un marco especialmente diseñado para realizar análisis de seguridad complejos en el código de bytes a través de la interpretación abstracta. Este mecanismo hace que el proceso de verificación sea más granular y preciso, y cada validador puede definir su estado abstracto único para el análisis.
Al inicio, el intérprete abstracto crea un gráfico de flujo de control (CFG) a partir de módulos compilados. Cada bloque básico en estos CFG mantiene un conjunto de estados, un "estado previo al pedido" y un "estado posterior al pedido". El "estado previo al pedido" proporciona una instantánea del estado del programa antes de la ejecución del bloque básico, mientras que el "estado posterior al pedido" proporciona una descripción del estado del programa después de la ejecución del bloque básico.
Cuando el intérprete abstracto no encuentra un salto (o bucle) en el gráfico de flujo de control, sigue un principio de ejecución lineal simple: cada bloque básico se analiza a su vez y la instrucción anterior se calcula de acuerdo con la semántica de cada instrucción en el bloque Estado secuencial y estado post-secuencial. El resultado es una instantánea precisa del estado de cada bloque básico durante la ejecución de un programa, lo que ayuda a verificar las propiedades de seguridad del programa.
Flujo de trabajo del intérprete abstracto Move
Sin embargo, el proceso se vuelve más complicado cuando hay bucles en el flujo de control. La aparición de un ciclo significa que el gráfico de flujo de control contiene un borde de salto hacia atrás. La fuente del borde de salto hacia atrás corresponde al estado subsiguiente del bloque básico actual, y el bloque básico de destino (cabeza de bucle) del salto- back edge es un previamente analizado Por lo tanto, el intérprete abstracto necesita fusionar cuidadosamente los estados de los dos bloques básicos relacionados con el jumpback.
Si se encuentra que el estado fusionado es diferente del estado de preorden existente del bloque básico de cabeza de bucle, el intérprete abstracto actualiza el estado del bloque básico de cabeza de bucle y reinicia el análisis a partir de este bloque básico. Este proceso de análisis iterativo continuará hasta que se estabilice el estado previo del bucle. En otras palabras, este proceso se repite hasta que el estado de preorden del bloque básico de cabeza de ciclo ya no cambia entre iteraciones. Alcanzar un punto fijo indica que el análisis del ciclo está completo.
Sui IDLeak Validator:
Análisis de Interpretación de Resumen Personalizado
A diferencia del diseño original de Move, la plataforma blockchain de Sui presenta un modelo de almacenamiento global único centrado en "objetivos". Una característica notable de este modelo es: cualquier estructura de datos con un atributo clave (almacenado en la cadena como un índice) debe tener el tipo ID como primer campo de la estructura. El campo ID es inmutable y no se puede transferir a otros objetos, ya que cada objeto debe tener una ID global única. Para garantizar estas propiedades, Sui creó un conjunto de lógica de análisis personalizada sobre el intérprete abstracto.
El verificador IDLeak, también conocido como id_leak_verifier, funciona junto con el intérprete abstracto para el análisis. Tiene su propio AbstractDomain único, llamado AbstractState. Cada AbstractState consiste en AbstractValue correspondiente a múltiples variables locales. AbstractValue supervisa el estado de cada variable local para rastrear si una variable de ID es nueva.
En el proceso de empaquetamiento de estructuras, el validador IDLeak solo permite empaquetar una identificación nueva en una estructura. Al abstraer el análisis de interpretación, los validadores de IDLeak pueden realizar un seguimiento exhaustivo del estado del flujo de datos local para garantizar que no se transfieran ID existentes a otros objetos de estructura.
Problema de inconsistencia en el mantenimiento del estado del validador Sui IDLeak
El validador IDLeak se integra con el intérprete abstracto de Move mediante la implementación de la función AbstractState::join. Esta función juega un papel integral en la gestión estatal, especialmente en la fusión y actualización de los valores estatales.
Examine estas funciones en detalle para comprender su funcionamiento:
En AbstractState::join, la función toma otro AbstractState como entrada e intenta fusionar su estado local con el estado local del objeto actual. Para cada variable local en el estado de entrada, compara el valor de esa variable con su valor actual en el estado local (el valor predeterminado es AbstractValue::Other si no se encuentra). Si los dos valores no son iguales, establecerá un indicador "cambiado" como base para determinar si el resultado final de la fusión del estado ha cambiado y actualizará el valor de la variable local en el estado local llamando a AbstractValue::join.
En AbstractValue::join, la función compara su valor con otro AbstractValue. Si son iguales, devolverá el valor pasado. Si no es igual, devuelve AbstractValue::Other.
Sin embargo, esta lógica de mantenimiento de estado contiene un problema de inconsistencia oculto. Aunque AbstractState::join devolverá un resultado que indica que el estado combinado ha cambiado (JoinResult::Changed) en función de la diferencia entre los valores nuevos y antiguos, el valor del estado actualizado combinado aún puede permanecer sin cambios.
Este problema de inconsistencia es causado por el orden de las operaciones: la decisión de cambiar el estado en AbstractState::join ocurre antes de la actualización del estado (AbstractValue::join), y esta decisión no refleja el resultado de la actualización del estado real.
Además, en AbstractValue::join, AbstractValue::Other juega un papel decisivo en el resultado de la fusión. Por ejemplo, si el valor antiguo es AbstractValue::Other y el nuevo valor es AbstractValue::Fresh, el valor de estado actualizado sigue siendo AbstractValue::Other, incluso si los valores antiguo y nuevo son diferentes, el estado en sí permanece sin cambios. después de la actualización.
Ejemplo: Incoherencia de conexiones con estado
Esto introduce una inconsistencia: el resultado de fusionar el estado de un bloque básico se considera "cambiado", pero el valor del estado fusionado en sí no ha cambiado. En el proceso de análisis de interpretación abstracta, tales inconsistencias pueden tener serias consecuencias. Revisamos el comportamiento de un intérprete abstracto cuando ocurre un ciclo en un gráfico de flujo de control (CFG):
Cuando se encuentra un bucle, el intérprete abstracto emplea un método de análisis iterativo para fusionar el estado del bloque básico de destino de salto hacia atrás y el bloque básico actual. Si el estado fusionado cambia, el intérprete abstracto volverá a analizar a partir del objetivo de salto.
Sin embargo, si la operación de fusión del análisis de interpretación abstracta marca erróneamente el resultado de la fusión del estado como "cambio", cuando en realidad el valor de la variable interna del estado no ha cambiado, conducirá a un reanálisis interminable, lo que resultará en un Bucle infinito.
Explotación adicional de inconsistencias
Activa un bucle infinito en el validador Sui IDLeak
Aprovechando esta inconsistencia, un atacante puede construir un gráfico de flujo de control malicioso que engaña a los validadores de IDLeak en un bucle infinito. Este diagrama de flujo de control cuidadosamente construido consta de tres bloques básicos: BB1 y BB2, BB3. Vale la pena señalar que intencionalmente introdujimos un borde de salto hacia atrás de BB3 a BB2 para construir un bucle.
El estado CFG+ malicioso puede conducir a un bucle infinito interno en el validador IDLeak
El proceso comienza con BB2, donde el AbstractValue de una variable local en particular se establece en ::Other. Después de ejecutar BB2, el flujo se transfiere a BB3, donde la misma variable se establece en ::Fresh. Al final de BB3, hay un borde de salto hacia atrás, saltando a BB2.
Las inconsistencias antes mencionadas juegan un papel clave en la interpretación abstracta de este ejemplo. Cuando se procesa el borde de salto hacia atrás, el intérprete abstracto intenta conectar el estado posterior al pedido de BB3 (con la variable ":: Fresco") con el estado previo al pedido de BB2 (con la variable ":: Otro"). La función AbstractState::join nota la diferencia entre los valores antiguos y nuevos y establece el indicador de "cambio" para indicar que BB2 debe volver a analizarse.
Sin embargo, el comportamiento dominante de "::Otro" en AbstractValue::join significa que después de fusionar AbstractValue, el valor real de la variable de estado BB2 sigue siendo "::Otro", y el resultado de la fusión de estado no ha cambiado .
Entonces, una vez que comienza este proceso cíclico, es decir, mientras los validadores continúan volviendo a analizar BB2 y todos sus nodos de bloque básicos sucesores (BB3 en este caso), continúa indefinidamente. El bucle infinito consume todos los ciclos de CPU disponibles, por lo que no puede procesar ni responder a nuevas transacciones, lo que persiste tras los reinicios del validador.
Al explotar esta vulnerabilidad, los nodos de validación se ejecutan sin cesar como hámsters en una rueda en un ciclo infinito, sin poder procesar nuevas transacciones. Por lo tanto, nos referimos a este tipo único de ataque como un ataque de "rueda de hámster".
El ataque de la "rueda de hámster" puede paralizar efectivamente a los validadores de Sui, lo que a su vez puede derribar toda la red de Sui.
Después de comprender la causa de la vulnerabilidad y el proceso de activación, construimos un ejemplo concreto mediante el uso de la siguiente simulación de Move bytecode y activamos con éxito la vulnerabilidad en la simulación en el entorno real:
Este ejemplo muestra cómo desencadenar la vulnerabilidad en un entorno real a través de un código de bytes cuidadosamente construido. Específicamente, un atacante podría desencadenar un bucle infinito en el validador IDLeak, consumiendo todos los ciclos de CPU de un nodo Sui con una carga útil de solo unos 100 bytes, evitando efectivamente el procesamiento de nuevas transacciones y provocando una denegación de servicio en la red Sui.
El ataque "Hamster Wheel" continúa dañando la red Sui
El programa de recompensas por errores de Sui tiene regulaciones estrictas sobre la evaluación de los niveles de vulnerabilidad, principalmente en función del grado de daño a toda la red. Las vulnerabilidades que cumplen con la calificación "crítica" deben apagar toda la red y evitar de manera efectiva nuevas confirmaciones de transacciones, y requieren una bifurcación dura para solucionar el problema; vulnerabilidades de (medio)" o "alto riesgo (alto)".
La vulnerabilidad de la "rueda de hámster" descubierta por el equipo de CertiK Skyfall puede apagar toda la red de Sui y requiere el lanzamiento oficial de una nueva versión para su actualización y reparación. Sui finalmente calificó la vulnerabilidad como "crítica" en función de su criticidad. Para comprender mejor el grave impacto causado por el ataque de la "rueda de hámster", es necesario que entendamos la compleja arquitectura del sistema backend de Sui, especialmente todo el proceso de publicación o actualización de transacciones en la cadena.
Descripción general de las interacciones para enviar transacciones en Sui
Inicialmente, las transacciones de los usuarios se envían a través de RPC de front-end y se pasan a los servicios de back-end después de una verificación básica. El servicio backend de Sui es responsable de validar aún más las cargas de transacciones entrantes. Después de verificar con éxito la firma del usuario, la transacción se convierte en un certificado de transacción (que contiene la información de la transacción y la firma de Sui).
Estos certificados de transacción son una parte fundamental del funcionamiento de la red Sui y pueden difundirse entre varios nodos de verificación de la red. Para las transacciones de creación/actualización de contratos, antes de que puedan cargarse en la cadena, el nodo de verificación llamará al verificador Sui para comprobar y verificar la validez de la estructura/semántica del contrato de estos certificados. Es durante esta etapa crítica de verificación que la vulnerabilidad de "bucle infinito" puede activarse y explotarse.
Cuando se activó la vulnerabilidad, provocó que el proceso de verificación se interrumpiera indefinidamente, lo que obstaculizó la capacidad del sistema para procesar nuevas transacciones y provocó que la red se cerrara por completo. Para colmo de males, la situación persistió después de que se reiniciaron los nodos, lo que significaba que las mitigaciones tradicionales estaban lejos de ser adecuadas. Una vez que se activa la vulnerabilidad, habrá un "daño continuo" y dejará un impacto duradero en toda la red de Sui.
La solución de Sui
Después de los comentarios de CertiK, Sui confirmó la vulnerabilidad de manera oportuna y lanzó una solución para abordar la falla crítica. La solución garantiza la consistencia entre los cambios de estado y los indicadores posteriores al cambio, lo que elimina el efecto crítico del ataque de la "rueda de hámster".
Para eliminar la incoherencia antes mencionada, la solución de Sui incluye un ajuste pequeño pero fundamental en la función AbstractState::join. Este parche elimina la lógica de determinar el resultado de la combinación de estados antes de ejecutar AbstractValue::join. En su lugar, ejecute primero la función AbstractValue::join para la combinación de estados y configure la combinación comparando el resultado de la actualización final con el valor de estado original (antiguo _value) Una bandera para los cambios.
De esta forma, el resultado de la fusión de estados será coherente con el resultado de la actualización real y no se producirá un bucle infinito durante el proceso de análisis.
Además de corregir esta vulnerabilidad específica, Sui también implementó mitigaciones para reducir el impacto de futuras vulnerabilidades del validador. De acuerdo con la respuesta de Sui en el informe de error, la mitigación implica una función llamada Denylist.
"Sin embargo, los validadores tienen un archivo de configuración de nodo que les permite rechazar temporalmente ciertas clases de transacciones. Esta configuración se puede usar para deshabilitar temporalmente el procesamiento de lanzamientos y actualizaciones de paquetes. Debido a este error, se está ejecutando Sui antes de firmar un lanzamiento o actualización de paquete tx validadores, mientras que la lista de denegación detendrá la ejecución del validador y eliminará el tx malicioso, denegar temporalmente estos tipos de tx es una mitigación 100% efectiva (aunque interrumpirá temporalmente el servicio para las personas que intentan liberar o actualizar el código).
Por cierto, hemos tenido este archivo de configuración de la lista de denegación de TX desde hace un tiempo, pero también hemos agregado un mecanismo similar para los certificados como una mitigación de seguimiento a su vulnerabilidad de "bucle de validación" informada anteriormente. Con este mecanismo, tendremos más flexibilidad frente a este ataque: utilizaremos la configuración de la lista de denegación de certificados para que los validadores se olviden de los certificados defectuosos (rompiendo el ciclo infinito), y la configuración de la lista de denegación de TX para prohibir la publicación/actualización, evitando así la creación de nuevas transacciones de ataques maliciosos. ¡Gracias por hacernos pensar en esto!
Un validador tiene un número limitado de "ticks" (diferentes al gas) para la verificación del bytecode antes de firmar una transacción, y si no se puede verificar todo el bytecode emitido en una transacción en este número de ticks, el validador se negará a firmar la transacción, impidiendo que se ejecute en la red. Anteriormente, la medición solo se aplicaba a un conjunto seleccionado de pases de validación complejos. Para combatir esto, extendemos la medición a cada validador para garantizar una restricción en el trabajo que realiza un validador durante el proceso de validación de cada tick. También solucionamos un posible error de bucle infinito en el validador de fugas de ID. "
--Explicación de los desarrolladores de Sui sobre las correcciones de errores
En general, Denylist permite a los validadores evitar temporalmente la explotación de vulnerabilidades en los validadores y prevenir de manera efectiva el daño potencial causado por algunas transacciones maliciosas al deshabilitar el proceso de lanzamiento o actualización. Cuando las medidas de mitigación de Denylist surten efecto, los nodos aseguran que pueden continuar trabajando sacrificando sus propias funciones de contrato de publicación/actualización.
Resumir
En este artículo, compartimos los detalles técnicos del ataque "Hamster Wheel" descubierto por el equipo de CertiK Skyfall, y explicamos cómo este nuevo tipo de ataque explota vulnerabilidades clave para provocar el cierre total de la red Sui. Además, también estudiamos cuidadosamente la respuesta oportuna de Sui para solucionar este problema crítico y compartimos la corrección de la vulnerabilidad y los métodos de mitigación posteriores para vulnerabilidades similares.
Ver originales
El contenido es solo de referencia, no una solicitud u oferta. No se proporciona asesoramiento fiscal, legal ni de inversión. Consulte el Descargo de responsabilidad para obtener más información sobre los riesgos.
Detalles técnicos y análisis en profundidad de la última vulnerabilidad de Sui "rueda de hámster"
Anteriormente, el equipo de CertiK descubrió una serie de vulnerabilidades de denegación de servicio en la cadena de bloques de Sui. Entre estas vulnerabilidades, se destaca una nueva vulnerabilidad de alto impacto. Esta vulnerabilidad puede hacer que los nodos de la red Sui no puedan procesar nuevas transacciones y el efecto es equivalente a un apagado completo de toda la red.
El lunes pasado, CertiK recibió una recompensa por errores de $ 500,000 de SUI por descubrir esta importante vulnerabilidad de seguridad. CoinDesk, un medio autorizado en la industria de EE. UU., informó sobre el evento, y luego los principales medios también publicaron noticias relacionadas después de su informe.
Esta vulnerabilidad de seguridad se llama vívidamente "Rueda de hámster": su método de ataque único es diferente de los ataques conocidos actualmente. El atacante solo necesita enviar una carga útil de aproximadamente 100 bytes para activar un bucle infinito en el nodo de verificación de Sui, lo que hace que no responda. a nuevas transacciones.
Además, el daño causado por el ataque puede continuar después de que se reinicie la red y puede propagarse automáticamente en la red Sui, lo que hace que todos los nodos no puedan procesar nuevas transacciones como hámsters corriendo sin cesar en la rueda. Por lo tanto, nos referimos a este tipo único de ataque como un ataque de "rueda de hámster".
Después de descubrir el error, CertiK se lo informó a Sui a través del programa de recompensas por errores de Sui. Sui también respondió de manera efectiva la primera vez, confirmó la gravedad de la vulnerabilidad y tomó activamente las medidas correspondientes para reparar el problema antes del lanzamiento de la red principal. Además de reparar esta vulnerabilidad en particular, Sui también implementó mitigaciones preventivas para reducir el daño potencial que podría causar esta vulnerabilidad.
Para agradecer al equipo de CertiK por su divulgación responsable, Sui otorgó al equipo de CertiK una recompensa de $500,000.
Los detalles de esta vulnerabilidad crítica se divulgarán a nivel técnico a continuación, y se aclararán la causa raíz y el impacto potencial de la vulnerabilidad.
Explicación de vulnerabilidad
El papel clave de los validadores en Sui
Para cadenas de bloques basadas en el lenguaje Move, como Sui y Aptos, el mecanismo de protección para prevenir ataques maliciosos de carga útil es principalmente tecnología de verificación estática. A través de la tecnología de verificación estática, Sui puede verificar la validez de la carga enviada por el usuario antes de que se emita o actualice el contrato. El validador proporciona una serie de verificadores para garantizar la corrección de la estructura y la semántica. Solo después de pasar la verificación de verificación, el contrato ingresará a la máquina virtual Move para ser ejecutado.
Amenazas maliciosas de carga útil en la cadena de movimiento
La cadena Sui proporciona un nuevo conjunto de modelos de almacenamiento e interfaces además de la máquina virtual Move original, por lo que Sui tiene una versión personalizada de la máquina virtual Move. Para admitir nuevas primitivas de almacenamiento, Sui presenta además una serie de métodos de inspección adicionales y personalizados para la verificación de seguridad de las cargas útiles que no son de confianza, como la seguridad de objetos y las funciones de acceso al almacenamiento global. Estos cheques personalizados se ajustan a las características únicas de Sui, por lo que los llamamos validadores de Sui.
El orden de Sui de controlar las cargas.
Como se muestra en la figura anterior, la mayoría de las comprobaciones en el verificador realizan una verificación de seguridad estructural contra CompiledModule (que representa la ejecución de la carga útil del contrato proporcionada por el usuario). Por ejemplo, use el "Comprobador de duplicados" para asegurarse de que no haya entradas duplicadas en la carga útil del tiempo de ejecución; use el "Verificador de límites" para asegurarse de que la longitud de cada campo en la carga útil del tiempo de ejecución esté dentro del límite de entrada máximo permitido.
Además de las comprobaciones estructurales, las comprobaciones estáticas del verificador aún requieren métodos de análisis más complejos para garantizar la solidez de las cargas útiles no confiables a nivel semántico.
Más información sobre el intérprete abstracto de Move:
Análisis lineal e iterativo
El intérprete abstracto proporcionado por Move es un marco especialmente diseñado para realizar análisis de seguridad complejos en el código de bytes a través de la interpretación abstracta. Este mecanismo hace que el proceso de verificación sea más granular y preciso, y cada validador puede definir su estado abstracto único para el análisis.
Al inicio, el intérprete abstracto crea un gráfico de flujo de control (CFG) a partir de módulos compilados. Cada bloque básico en estos CFG mantiene un conjunto de estados, un "estado previo al pedido" y un "estado posterior al pedido". El "estado previo al pedido" proporciona una instantánea del estado del programa antes de la ejecución del bloque básico, mientras que el "estado posterior al pedido" proporciona una descripción del estado del programa después de la ejecución del bloque básico.
Cuando el intérprete abstracto no encuentra un salto (o bucle) en el gráfico de flujo de control, sigue un principio de ejecución lineal simple: cada bloque básico se analiza a su vez y la instrucción anterior se calcula de acuerdo con la semántica de cada instrucción en el bloque Estado secuencial y estado post-secuencial. El resultado es una instantánea precisa del estado de cada bloque básico durante la ejecución de un programa, lo que ayuda a verificar las propiedades de seguridad del programa.
Flujo de trabajo del intérprete abstracto Move
Sin embargo, el proceso se vuelve más complicado cuando hay bucles en el flujo de control. La aparición de un ciclo significa que el gráfico de flujo de control contiene un borde de salto hacia atrás. La fuente del borde de salto hacia atrás corresponde al estado subsiguiente del bloque básico actual, y el bloque básico de destino (cabeza de bucle) del salto- back edge es un previamente analizado Por lo tanto, el intérprete abstracto necesita fusionar cuidadosamente los estados de los dos bloques básicos relacionados con el jumpback.
Si se encuentra que el estado fusionado es diferente del estado de preorden existente del bloque básico de cabeza de bucle, el intérprete abstracto actualiza el estado del bloque básico de cabeza de bucle y reinicia el análisis a partir de este bloque básico. Este proceso de análisis iterativo continuará hasta que se estabilice el estado previo del bucle. En otras palabras, este proceso se repite hasta que el estado de preorden del bloque básico de cabeza de ciclo ya no cambia entre iteraciones. Alcanzar un punto fijo indica que el análisis del ciclo está completo.
Sui IDLeak Validator:
Análisis de Interpretación de Resumen Personalizado
A diferencia del diseño original de Move, la plataforma blockchain de Sui presenta un modelo de almacenamiento global único centrado en "objetivos". Una característica notable de este modelo es: cualquier estructura de datos con un atributo clave (almacenado en la cadena como un índice) debe tener el tipo ID como primer campo de la estructura. El campo ID es inmutable y no se puede transferir a otros objetos, ya que cada objeto debe tener una ID global única. Para garantizar estas propiedades, Sui creó un conjunto de lógica de análisis personalizada sobre el intérprete abstracto.
El verificador IDLeak, también conocido como id_leak_verifier, funciona junto con el intérprete abstracto para el análisis. Tiene su propio AbstractDomain único, llamado AbstractState. Cada AbstractState consiste en AbstractValue correspondiente a múltiples variables locales. AbstractValue supervisa el estado de cada variable local para rastrear si una variable de ID es nueva.
En el proceso de empaquetamiento de estructuras, el validador IDLeak solo permite empaquetar una identificación nueva en una estructura. Al abstraer el análisis de interpretación, los validadores de IDLeak pueden realizar un seguimiento exhaustivo del estado del flujo de datos local para garantizar que no se transfieran ID existentes a otros objetos de estructura.
Problema de inconsistencia en el mantenimiento del estado del validador Sui IDLeak
El validador IDLeak se integra con el intérprete abstracto de Move mediante la implementación de la función AbstractState::join. Esta función juega un papel integral en la gestión estatal, especialmente en la fusión y actualización de los valores estatales.
Examine estas funciones en detalle para comprender su funcionamiento:
En AbstractState::join, la función toma otro AbstractState como entrada e intenta fusionar su estado local con el estado local del objeto actual. Para cada variable local en el estado de entrada, compara el valor de esa variable con su valor actual en el estado local (el valor predeterminado es AbstractValue::Other si no se encuentra). Si los dos valores no son iguales, establecerá un indicador "cambiado" como base para determinar si el resultado final de la fusión del estado ha cambiado y actualizará el valor de la variable local en el estado local llamando a AbstractValue::join.
En AbstractValue::join, la función compara su valor con otro AbstractValue. Si son iguales, devolverá el valor pasado. Si no es igual, devuelve AbstractValue::Other.
Sin embargo, esta lógica de mantenimiento de estado contiene un problema de inconsistencia oculto. Aunque AbstractState::join devolverá un resultado que indica que el estado combinado ha cambiado (JoinResult::Changed) en función de la diferencia entre los valores nuevos y antiguos, el valor del estado actualizado combinado aún puede permanecer sin cambios.
Este problema de inconsistencia es causado por el orden de las operaciones: la decisión de cambiar el estado en AbstractState::join ocurre antes de la actualización del estado (AbstractValue::join), y esta decisión no refleja el resultado de la actualización del estado real.
Además, en AbstractValue::join, AbstractValue::Other juega un papel decisivo en el resultado de la fusión. Por ejemplo, si el valor antiguo es AbstractValue::Other y el nuevo valor es AbstractValue::Fresh, el valor de estado actualizado sigue siendo AbstractValue::Other, incluso si los valores antiguo y nuevo son diferentes, el estado en sí permanece sin cambios. después de la actualización.
Ejemplo: Incoherencia de conexiones con estado
Esto introduce una inconsistencia: el resultado de fusionar el estado de un bloque básico se considera "cambiado", pero el valor del estado fusionado en sí no ha cambiado. En el proceso de análisis de interpretación abstracta, tales inconsistencias pueden tener serias consecuencias. Revisamos el comportamiento de un intérprete abstracto cuando ocurre un ciclo en un gráfico de flujo de control (CFG):
Cuando se encuentra un bucle, el intérprete abstracto emplea un método de análisis iterativo para fusionar el estado del bloque básico de destino de salto hacia atrás y el bloque básico actual. Si el estado fusionado cambia, el intérprete abstracto volverá a analizar a partir del objetivo de salto.
Sin embargo, si la operación de fusión del análisis de interpretación abstracta marca erróneamente el resultado de la fusión del estado como "cambio", cuando en realidad el valor de la variable interna del estado no ha cambiado, conducirá a un reanálisis interminable, lo que resultará en un Bucle infinito.
Explotación adicional de inconsistencias
Activa un bucle infinito en el validador Sui IDLeak
Aprovechando esta inconsistencia, un atacante puede construir un gráfico de flujo de control malicioso que engaña a los validadores de IDLeak en un bucle infinito. Este diagrama de flujo de control cuidadosamente construido consta de tres bloques básicos: BB1 y BB2, BB3. Vale la pena señalar que intencionalmente introdujimos un borde de salto hacia atrás de BB3 a BB2 para construir un bucle.
El estado CFG+ malicioso puede conducir a un bucle infinito interno en el validador IDLeak
El proceso comienza con BB2, donde el AbstractValue de una variable local en particular se establece en ::Other. Después de ejecutar BB2, el flujo se transfiere a BB3, donde la misma variable se establece en ::Fresh. Al final de BB3, hay un borde de salto hacia atrás, saltando a BB2.
Las inconsistencias antes mencionadas juegan un papel clave en la interpretación abstracta de este ejemplo. Cuando se procesa el borde de salto hacia atrás, el intérprete abstracto intenta conectar el estado posterior al pedido de BB3 (con la variable ":: Fresco") con el estado previo al pedido de BB2 (con la variable ":: Otro"). La función AbstractState::join nota la diferencia entre los valores antiguos y nuevos y establece el indicador de "cambio" para indicar que BB2 debe volver a analizarse.
Sin embargo, el comportamiento dominante de "::Otro" en AbstractValue::join significa que después de fusionar AbstractValue, el valor real de la variable de estado BB2 sigue siendo "::Otro", y el resultado de la fusión de estado no ha cambiado .
Entonces, una vez que comienza este proceso cíclico, es decir, mientras los validadores continúan volviendo a analizar BB2 y todos sus nodos de bloque básicos sucesores (BB3 en este caso), continúa indefinidamente. El bucle infinito consume todos los ciclos de CPU disponibles, por lo que no puede procesar ni responder a nuevas transacciones, lo que persiste tras los reinicios del validador.
Al explotar esta vulnerabilidad, los nodos de validación se ejecutan sin cesar como hámsters en una rueda en un ciclo infinito, sin poder procesar nuevas transacciones. Por lo tanto, nos referimos a este tipo único de ataque como un ataque de "rueda de hámster".
El ataque de la "rueda de hámster" puede paralizar efectivamente a los validadores de Sui, lo que a su vez puede derribar toda la red de Sui.
Después de comprender la causa de la vulnerabilidad y el proceso de activación, construimos un ejemplo concreto mediante el uso de la siguiente simulación de Move bytecode y activamos con éxito la vulnerabilidad en la simulación en el entorno real:
Este ejemplo muestra cómo desencadenar la vulnerabilidad en un entorno real a través de un código de bytes cuidadosamente construido. Específicamente, un atacante podría desencadenar un bucle infinito en el validador IDLeak, consumiendo todos los ciclos de CPU de un nodo Sui con una carga útil de solo unos 100 bytes, evitando efectivamente el procesamiento de nuevas transacciones y provocando una denegación de servicio en la red Sui.
El ataque "Hamster Wheel" continúa dañando la red Sui
El programa de recompensas por errores de Sui tiene regulaciones estrictas sobre la evaluación de los niveles de vulnerabilidad, principalmente en función del grado de daño a toda la red. Las vulnerabilidades que cumplen con la calificación "crítica" deben apagar toda la red y evitar de manera efectiva nuevas confirmaciones de transacciones, y requieren una bifurcación dura para solucionar el problema; vulnerabilidades de (medio)" o "alto riesgo (alto)".
La vulnerabilidad de la "rueda de hámster" descubierta por el equipo de CertiK Skyfall puede apagar toda la red de Sui y requiere el lanzamiento oficial de una nueva versión para su actualización y reparación. Sui finalmente calificó la vulnerabilidad como "crítica" en función de su criticidad. Para comprender mejor el grave impacto causado por el ataque de la "rueda de hámster", es necesario que entendamos la compleja arquitectura del sistema backend de Sui, especialmente todo el proceso de publicación o actualización de transacciones en la cadena.
Descripción general de las interacciones para enviar transacciones en Sui
Inicialmente, las transacciones de los usuarios se envían a través de RPC de front-end y se pasan a los servicios de back-end después de una verificación básica. El servicio backend de Sui es responsable de validar aún más las cargas de transacciones entrantes. Después de verificar con éxito la firma del usuario, la transacción se convierte en un certificado de transacción (que contiene la información de la transacción y la firma de Sui).
Estos certificados de transacción son una parte fundamental del funcionamiento de la red Sui y pueden difundirse entre varios nodos de verificación de la red. Para las transacciones de creación/actualización de contratos, antes de que puedan cargarse en la cadena, el nodo de verificación llamará al verificador Sui para comprobar y verificar la validez de la estructura/semántica del contrato de estos certificados. Es durante esta etapa crítica de verificación que la vulnerabilidad de "bucle infinito" puede activarse y explotarse.
Cuando se activó la vulnerabilidad, provocó que el proceso de verificación se interrumpiera indefinidamente, lo que obstaculizó la capacidad del sistema para procesar nuevas transacciones y provocó que la red se cerrara por completo. Para colmo de males, la situación persistió después de que se reiniciaron los nodos, lo que significaba que las mitigaciones tradicionales estaban lejos de ser adecuadas. Una vez que se activa la vulnerabilidad, habrá un "daño continuo" y dejará un impacto duradero en toda la red de Sui.
La solución de Sui
Después de los comentarios de CertiK, Sui confirmó la vulnerabilidad de manera oportuna y lanzó una solución para abordar la falla crítica. La solución garantiza la consistencia entre los cambios de estado y los indicadores posteriores al cambio, lo que elimina el efecto crítico del ataque de la "rueda de hámster".
Para eliminar la incoherencia antes mencionada, la solución de Sui incluye un ajuste pequeño pero fundamental en la función AbstractState::join. Este parche elimina la lógica de determinar el resultado de la combinación de estados antes de ejecutar AbstractValue::join. En su lugar, ejecute primero la función AbstractValue::join para la combinación de estados y configure la combinación comparando el resultado de la actualización final con el valor de estado original (antiguo _value) Una bandera para los cambios.
De esta forma, el resultado de la fusión de estados será coherente con el resultado de la actualización real y no se producirá un bucle infinito durante el proceso de análisis.
Además de corregir esta vulnerabilidad específica, Sui también implementó mitigaciones para reducir el impacto de futuras vulnerabilidades del validador. De acuerdo con la respuesta de Sui en el informe de error, la mitigación implica una función llamada Denylist.
"Sin embargo, los validadores tienen un archivo de configuración de nodo que les permite rechazar temporalmente ciertas clases de transacciones. Esta configuración se puede usar para deshabilitar temporalmente el procesamiento de lanzamientos y actualizaciones de paquetes. Debido a este error, se está ejecutando Sui antes de firmar un lanzamiento o actualización de paquete tx validadores, mientras que la lista de denegación detendrá la ejecución del validador y eliminará el tx malicioso, denegar temporalmente estos tipos de tx es una mitigación 100% efectiva (aunque interrumpirá temporalmente el servicio para las personas que intentan liberar o actualizar el código).
Por cierto, hemos tenido este archivo de configuración de la lista de denegación de TX desde hace un tiempo, pero también hemos agregado un mecanismo similar para los certificados como una mitigación de seguimiento a su vulnerabilidad de "bucle de validación" informada anteriormente. Con este mecanismo, tendremos más flexibilidad frente a este ataque: utilizaremos la configuración de la lista de denegación de certificados para que los validadores se olviden de los certificados defectuosos (rompiendo el ciclo infinito), y la configuración de la lista de denegación de TX para prohibir la publicación/actualización, evitando así la creación de nuevas transacciones de ataques maliciosos. ¡Gracias por hacernos pensar en esto!
Un validador tiene un número limitado de "ticks" (diferentes al gas) para la verificación del bytecode antes de firmar una transacción, y si no se puede verificar todo el bytecode emitido en una transacción en este número de ticks, el validador se negará a firmar la transacción, impidiendo que se ejecute en la red. Anteriormente, la medición solo se aplicaba a un conjunto seleccionado de pases de validación complejos. Para combatir esto, extendemos la medición a cada validador para garantizar una restricción en el trabajo que realiza un validador durante el proceso de validación de cada tick. También solucionamos un posible error de bucle infinito en el validador de fugas de ID. "
--Explicación de los desarrolladores de Sui sobre las correcciones de errores
En general, Denylist permite a los validadores evitar temporalmente la explotación de vulnerabilidades en los validadores y prevenir de manera efectiva el daño potencial causado por algunas transacciones maliciosas al deshabilitar el proceso de lanzamiento o actualización. Cuando las medidas de mitigación de Denylist surten efecto, los nodos aseguran que pueden continuar trabajando sacrificando sus propias funciones de contrato de publicación/actualización.
Resumir
En este artículo, compartimos los detalles técnicos del ataque "Hamster Wheel" descubierto por el equipo de CertiK Skyfall, y explicamos cómo este nuevo tipo de ataque explota vulnerabilidades clave para provocar el cierre total de la red Sui. Además, también estudiamos cuidadosamente la respuesta oportuna de Sui para solucionar este problema crítico y compartimos la corrección de la vulnerabilidad y los métodos de mitigación posteriores para vulnerabilidades similares.