Análisis de vulnerabilidades del compilador Solidity y estrategias de respuesta
El compilador es uno de los componentes centrales de los sistemas informáticos modernos. Convierte lenguajes de programación de alto nivel, comprensibles para los humanos, en instrucciones de bajo nivel que pueden ser ejecutadas por la computadora. Aunque los desarrolladores y los expertos en seguridad suelen centrarse en la seguridad del código de las aplicaciones, los problemas de seguridad del propio compilador tampoco deben ser ignorados. Las vulnerabilidades del compilador pueden, en ciertos casos, dar lugar a riesgos de seguridad graves.
Tomando como ejemplo un navegador, durante el análisis y ejecución del código JavaScript, las vulnerabilidades del motor de JavaScript pueden permitir que los usuarios sufran ataques de ejecución remota de código al acceder a páginas web maliciosas, lo que finalmente podría dar a los atacantes el control del navegador de la víctima e incluso del sistema operativo. Además, los errores en los compiladores de C++ también pueden provocar consecuencias graves como la ejecución remota de código.
El compilador de Solidity no es una excepción, existen vulnerabilidades de seguridad en varias versiones. La función del compilador de Solidity es convertir el código de los contratos inteligentes en código de instrucciones para la máquina virtual de Ethereum (EVM), que se ejecutan finalmente en la EVM. Es importante notar que las vulnerabilidades del compilador de Solidity son diferentes de las vulnerabilidades de la EVM en sí. Las vulnerabilidades de la EVM se refieren a problemas de seguridad que ocurren al ejecutar instrucciones en la máquina virtual, lo que puede afectar toda la red de Ethereum. Por otro lado, las vulnerabilidades del compilador de Solidity son problemas que surgen al convertir Solidity en código EVM.
Una de las amenazas de los errores en el compilador de Solidity es que el código EVM generado puede no coincidir con las expectativas del desarrollador. Dado que los contratos inteligentes a menudo involucran los activos de criptomonedas de los usuarios, cualquier error causado por el compilador podría resultar en la pérdida de activos de los usuarios, lo que tendría consecuencias muy graves. Los desarrolladores y auditores suelen centrarse en la implementación lógica del contrato y en vulnerabilidades comunes, mientras que las vulnerabilidades del compilador requieren un análisis específico basado en la versión y el patrón de código.
A continuación, se presentan varios casos reales para mostrar las formas específicas, causas y peligros de las vulnerabilidades del compilador de Solidity.
SOL-2016-9 HighOrderByteCleanStorage
La vulnerabilidad existe en versiones anteriores del compilador de Solidity (>=0.1.6 <0.4.4).
Considera el siguiente código:
solidez
contrato C {
uint32 a = 0x12345678;
uint32 b = 0;
función f() pública {
a = a + 1;
}
function run() public view returns (uint32) {
return b;
}
}
La variable b no ha sido modificada, la función run() debería devolver el valor predeterminado 0. Sin embargo, en el código generado por la versión vulnerable del compilador, run() devuelve 1.
Esta inconsistencia es difícil de detectar a través de una simple revisión de código. Aunque el código de ejemplo tiene un impacto limitado, las consecuencias serían muy graves si la variable b se utiliza para la verificación de permisos o la contabilidad de activos.
La causa de este problema radica en que el EVM utiliza elementos de pila de 32 bytes de tamaño, mientras que cada slot del almacenamiento subyacente también es de 32 bytes. Solidity admite tipos de datos de menos de 32 bytes, como uint32, y el compilador necesita limpiar los bits altos al manejar estos tipos para garantizar la corrección de los datos. En este caso, después de la sobrecarga de la suma, el compilador no limpió correctamente los bits altos del resultado, lo que llevó a que el bit de desbordamiento de 1 se escribiera en el almacenamiento, sobrescribiendo la variable b.
SOL-2022-4 Efectos secundarios de memoria en InlineAssembly
Esta vulnerabilidad existe en los compiladores de las versiones 0.8.13 a 0.8.15. Considere el siguiente código:
solidez
contrato C {
function f() public pure returns (uint) {
ensamblaje {
mstore(0, 0x42)
}
uint x;
ensamblaje {
x := mload(0)
}
return x;
}
}
El compilador de Solidity realiza un análisis profundo del flujo de control y de datos durante el proceso de optimización, con el fin de reducir el tamaño del código generado y optimizar el consumo de gas. Aunque esta optimización es común, debido a la complejidad de las situaciones, es fácil que surjan errores o vulnerabilidades de seguridad.
El problema del código anterior proviene de este tipo de optimización. El compilador considera que si una función modifica los datos en la dirección de memoria 0, pero no se utilizan esos datos posteriormente, puede eliminar las instrucciones de modificación para ahorrar gas. Sin embargo, esta optimización solo se aplica dentro de un bloque de ensamblaje individual.
En este ejemplo, la escritura y el acceso a la memoria 0 están en dos bloques de ensamblaje diferentes. El compilador solo analizó los bloques de ensamblaje por separado, considerando que la escritura en el primer bloque era redundante, por lo que la eliminó, lo que generó un error. En la versión con vulnerabilidad, la función f() devolverá 0, mientras que el valor de retorno correcto debería ser 0x42.
SOL-2022-6 Overflow de Encabezado de Reencoding Abi con Limpieza de Arreglo Estático
Esta vulnerabilidad afecta a los compiladores de las versiones 0.5.8 a 0.8.16. Considere el siguiente código:
En condiciones normales, este código debería devolver el valor de la variable a "aaaa". Pero en la versión con vulnerabilidad, devolverá una cadena vacía "".
El problema radica en que Solidity realiza una operación abi.encode en arreglos de tipo calldata y, erróneamente, limpia ciertos datos, lo que provoca que se modifiquen datos adyacentes, causando una inconsistencia en los datos después de la codificación y decodificación.
Es importante destacar que Solidity realiza implícitamente abi.encode en los parámetros al realizar llamadas externas y emitir eventos, por lo que el alcance de esta vulnerabilidad puede ser mayor de lo esperado.
Consejos de seguridad
Basado en el análisis de las vulnerabilidades del compilador de Solidity, se presentan las siguientes recomendaciones para desarrolladores y personal de seguridad:
Para los desarrolladores:
Utiliza una versión más reciente del compilador de Solidity. Aunque las nuevas versiones pueden introducir nuevos problemas, generalmente hay menos problemas de seguridad conocidos.
Mejorar las pruebas unitarias. La mayoría de los errores a nivel de compilador pueden llevar a que los resultados de ejecución no coincidan con las expectativas; estos problemas son difíciles de detectar mediante la revisión de código, pero son fáciles de exponer durante las pruebas. Aumentar la cobertura del código puede minimizar este tipo de problemas.
Evite el uso de ensamblaje en línea, operaciones complejas de codificación y decodificación de ABI, y no use ciegamente nuevas características y funciones experimentales. La mayoría de las vulnerabilidades históricas están relacionadas con estas operaciones complejas.
Para el personal de seguridad:
No ignore los riesgos de seguridad que el compilador puede introducir durante la auditoría. El ítem correspondiente en la Clasificación de Debilidades de Contratos Inteligentes ) SWC [0] es SWC-102: Versión de Compilador Obsoleta.
En el proceso de desarrollo de SDL, instar al equipo de desarrollo a actualizar la versión del compilador, considerando la introducción de una verificación automática de la versión del compilador en CI/CD.
No es necesario preocuparse en exceso por las vulnerabilidades del compilador. La mayoría de las vulnerabilidades solo se activan en patrones de código específicos; el uso de contratos compilados con versiones vulnerables no necesariamente implica un riesgo, debe evaluarse según las circunstancias específicas.
Algunos recursos prácticos:
Alertas de seguridad publicadas regularmente por el equipo de Solidity
Lista de errores actualizada periódicamente en el repositorio oficial de Solidity
Lista de errores del compilador de cada versión, que se puede utilizar para la verificación automática en CI/CD.
El ícono de advertencia en la esquina superior derecha de la página de código del contrato de Etherscan puede indicar vulnerabilidades de seguridad en la versión actual del compilador.
Resumen
Este artículo introduce el concepto de vulnerabilidades en el compilador de Solidity, analiza los riesgos de seguridad que pueden surgir en el desarrollo de Ethereum y proporciona consejos prácticos de seguridad para desarrolladores y personal de seguridad. Aunque las vulnerabilidades del compilador no son comunes, tienen un impacto profundo y merecen la atención de los equipos de desarrollo y seguridad.
Esta página puede contener contenido de terceros, que se proporciona únicamente con fines informativos (sin garantías ni declaraciones) y no debe considerarse como un respaldo por parte de Gate a las opiniones expresadas ni como asesoramiento financiero o profesional. Consulte el Descargo de responsabilidad para obtener más detalles.
10 me gusta
Recompensa
10
5
Compartir
Comentar
0/400
0xInsomnia
· 07-24 15:11
La capa inferior tiene fallos, la capa superior no va a ayudar.
Ver originalesResponder0
0xSunnyDay
· 07-24 06:35
¿Quién se atreve a decir que los compiladores son seguros?
Ver originalesResponder0
BankruptcyArtist
· 07-24 06:29
Buscando vulnerabilidades todos los días, en quiebra todos los días.
Ver originalesResponder0
bridge_anxiety
· 07-24 06:23
¡El coeficiente de dificultad de explotación es un golpe crítico!
Ver originalesResponder0
TokenDustCollector
· 07-24 06:13
Las vulnerabilidades de seguridad son el comienzo de que los tontos pierdan dinero.
Análisis de vulnerabilidades del compilador Solidity: impacto, casos y estrategias de respuesta
Análisis de vulnerabilidades del compilador Solidity y estrategias de respuesta
El compilador es uno de los componentes centrales de los sistemas informáticos modernos. Convierte lenguajes de programación de alto nivel, comprensibles para los humanos, en instrucciones de bajo nivel que pueden ser ejecutadas por la computadora. Aunque los desarrolladores y los expertos en seguridad suelen centrarse en la seguridad del código de las aplicaciones, los problemas de seguridad del propio compilador tampoco deben ser ignorados. Las vulnerabilidades del compilador pueden, en ciertos casos, dar lugar a riesgos de seguridad graves.
Tomando como ejemplo un navegador, durante el análisis y ejecución del código JavaScript, las vulnerabilidades del motor de JavaScript pueden permitir que los usuarios sufran ataques de ejecución remota de código al acceder a páginas web maliciosas, lo que finalmente podría dar a los atacantes el control del navegador de la víctima e incluso del sistema operativo. Además, los errores en los compiladores de C++ también pueden provocar consecuencias graves como la ejecución remota de código.
El compilador de Solidity no es una excepción, existen vulnerabilidades de seguridad en varias versiones. La función del compilador de Solidity es convertir el código de los contratos inteligentes en código de instrucciones para la máquina virtual de Ethereum (EVM), que se ejecutan finalmente en la EVM. Es importante notar que las vulnerabilidades del compilador de Solidity son diferentes de las vulnerabilidades de la EVM en sí. Las vulnerabilidades de la EVM se refieren a problemas de seguridad que ocurren al ejecutar instrucciones en la máquina virtual, lo que puede afectar toda la red de Ethereum. Por otro lado, las vulnerabilidades del compilador de Solidity son problemas que surgen al convertir Solidity en código EVM.
Una de las amenazas de los errores en el compilador de Solidity es que el código EVM generado puede no coincidir con las expectativas del desarrollador. Dado que los contratos inteligentes a menudo involucran los activos de criptomonedas de los usuarios, cualquier error causado por el compilador podría resultar en la pérdida de activos de los usuarios, lo que tendría consecuencias muy graves. Los desarrolladores y auditores suelen centrarse en la implementación lógica del contrato y en vulnerabilidades comunes, mientras que las vulnerabilidades del compilador requieren un análisis específico basado en la versión y el patrón de código.
A continuación, se presentan varios casos reales para mostrar las formas específicas, causas y peligros de las vulnerabilidades del compilador de Solidity.
SOL-2016-9 HighOrderByteCleanStorage
La vulnerabilidad existe en versiones anteriores del compilador de Solidity (>=0.1.6 <0.4.4).
Considera el siguiente código:
solidez contrato C { uint32 a = 0x12345678; uint32 b = 0; función f() pública { a = a + 1; } function run() public view returns (uint32) { return b; } }
La variable b no ha sido modificada, la función run() debería devolver el valor predeterminado 0. Sin embargo, en el código generado por la versión vulnerable del compilador, run() devuelve 1.
Esta inconsistencia es difícil de detectar a través de una simple revisión de código. Aunque el código de ejemplo tiene un impacto limitado, las consecuencias serían muy graves si la variable b se utiliza para la verificación de permisos o la contabilidad de activos.
La causa de este problema radica en que el EVM utiliza elementos de pila de 32 bytes de tamaño, mientras que cada slot del almacenamiento subyacente también es de 32 bytes. Solidity admite tipos de datos de menos de 32 bytes, como uint32, y el compilador necesita limpiar los bits altos al manejar estos tipos para garantizar la corrección de los datos. En este caso, después de la sobrecarga de la suma, el compilador no limpió correctamente los bits altos del resultado, lo que llevó a que el bit de desbordamiento de 1 se escribiera en el almacenamiento, sobrescribiendo la variable b.
SOL-2022-4 Efectos secundarios de memoria en InlineAssembly
Esta vulnerabilidad existe en los compiladores de las versiones 0.8.13 a 0.8.15. Considere el siguiente código:
solidez contrato C { function f() public pure returns (uint) { ensamblaje { mstore(0, 0x42) } uint x; ensamblaje { x := mload(0) } return x; } }
El compilador de Solidity realiza un análisis profundo del flujo de control y de datos durante el proceso de optimización, con el fin de reducir el tamaño del código generado y optimizar el consumo de gas. Aunque esta optimización es común, debido a la complejidad de las situaciones, es fácil que surjan errores o vulnerabilidades de seguridad.
El problema del código anterior proviene de este tipo de optimización. El compilador considera que si una función modifica los datos en la dirección de memoria 0, pero no se utilizan esos datos posteriormente, puede eliminar las instrucciones de modificación para ahorrar gas. Sin embargo, esta optimización solo se aplica dentro de un bloque de ensamblaje individual.
En este ejemplo, la escritura y el acceso a la memoria 0 están en dos bloques de ensamblaje diferentes. El compilador solo analizó los bloques de ensamblaje por separado, considerando que la escritura en el primer bloque era redundante, por lo que la eliminó, lo que generó un error. En la versión con vulnerabilidad, la función f() devolverá 0, mientras que el valor de retorno correcto debería ser 0x42.
SOL-2022-6 Overflow de Encabezado de Reencoding Abi con Limpieza de Arreglo Estático
Esta vulnerabilidad afecta a los compiladores de las versiones 0.5.8 a 0.8.16. Considere el siguiente código:
solidez contrato C { función f(string) calldata a( externo puro devuelve [1]string memory) { return abi.decode(abi.encode)a(, (string)([1]); } }
En condiciones normales, este código debería devolver el valor de la variable a "aaaa". Pero en la versión con vulnerabilidad, devolverá una cadena vacía "".
El problema radica en que Solidity realiza una operación abi.encode en arreglos de tipo calldata y, erróneamente, limpia ciertos datos, lo que provoca que se modifiquen datos adyacentes, causando una inconsistencia en los datos después de la codificación y decodificación.
Es importante destacar que Solidity realiza implícitamente abi.encode en los parámetros al realizar llamadas externas y emitir eventos, por lo que el alcance de esta vulnerabilidad puede ser mayor de lo esperado.
Consejos de seguridad
Basado en el análisis de las vulnerabilidades del compilador de Solidity, se presentan las siguientes recomendaciones para desarrolladores y personal de seguridad:
Para los desarrolladores:
Para el personal de seguridad:
Algunos recursos prácticos:
Resumen
Este artículo introduce el concepto de vulnerabilidades en el compilador de Solidity, analiza los riesgos de seguridad que pueden surgir en el desarrollo de Ethereum y proporciona consejos prácticos de seguridad para desarrolladores y personal de seguridad. Aunque las vulnerabilidades del compilador no son comunes, tienen un impacto profundo y merecen la atención de los equipos de desarrollo y seguridad.