Back to Blog

#10: Incidente ThirdWeb: Incompatibilidad Entre Módulos de Confianza Expone una Vulnerabilidad

Code AuditingPhalcon Security
February 22, 2024
8 min read
Key Insights

El 5 de diciembre de 2023, la destacada plataforma de desarrollo Web3 Thirdweb reveló vulnerabilidades de seguridad significativas en contratos inteligentes que afectaban a sus contratos precompilados. Esta falla crítica impactó a todos los tokens ERC-20, ERC-721 y ERC-1155 desplegados mediante estos contratos vulnerables específicos. En los días posteriores a la divulgación, los tokens desplegados con estos contratos vulnerables fueron progresivamente explotados en una serie de ataques, lo que subraya la gravedad de la incompatibilidad subyacente.

Comprendiendo la Vulnerabilidad del Contrato Inteligente de ThirdWeb

La causa raíz del incidente de ThirdWeb radica en la interacción inesperada entre dos componentes fundamentales del desarrollo de contratos inteligentes: ERC-2771 y la implementación de Multicall de OpenZeppelin. Para comprender completamente la vulnerabilidad, es esencial entender cada componente de forma individual y luego cómo su interacción creó una vía explotable.

ERC-2771: Meta-Transacciones y Reenviadores de Confianza

EIP-2771 define un protocolo a nivel de contrato que permite a los contratos Recipient aceptar meta-transactions a través de contratos Forwarder de confianza. Este estándar es crucial para mejorar la experiencia del usuario al permitir que terceros (reenviadores) paguen las tarifas de gas en nombre de los usuarios, abstrayendo la necesidad de que los usuarios posean tokens nativos de blockchain.

En la práctica, el ERC2771Context de OpenZeppelin es una implementación ampliamente adoptada. Su funcionalidad principal consiste en tratar los últimos 20 bytes del calldata de un reenviador de confianza como el _msgSender() efectivo. Para los desarrolladores que utilizan esta biblioteca, la práctica habitual es reemplazar todos los usos directos de msg.sender con _msgSender() para garantizar la compatibilidad con las meta-transacciones. De manera similar, _msgData() se utiliza para recuperar los datos de la transacción original, excluyendo la información del remitente añadida.

function _msgSender() internal view virtual override returns (address) {
    uint256 calldataLength = msg.data.length;
    uint256 contextSuffixLength = _contextSuffixLength();
    if (isTrustedForwarder(msg.sender) && calldataLength >= contextSuffixLength) {
        return address(bytes20(msg.data[calldataLength - contextSuffixLength:]));
    } else {
        return super._msgSender();
    }
}

function _msgData() internal view virtual override returns (bytes calldata) {
    uint256 calldataLength = msg.data.length;
    uint256 contextSuffixLength = _contextSuffixLength();
    if (isTrustedForwarder(msg.sender) && calldataLength >= contextSuffixLength) {
        return msg.data[:calldataLength - contextSuffixLength];
    } else {
        return super._msgData();
    }
}

Multicall: Agrupación de Transacciones para Mayor Eficiencia

La funcionalidad Multicall permite a los usuarios agrupar múltiples llamadas a funciones en una sola transacción, reduciendo significativamente los costos de gas y mejorando la eficiencia de las transacciones. El MulticallUpgradeable de OpenZeppelin es una implementación popular para este propósito. Toma un array de bytes de calldata y realiza un delegatecall para cada entrada, ejecutándolas dentro del contexto del contrato que realiza la llamada.

function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {
    results = new bytes[](data.length);
    for (uint256 i = 0; i < data.length; i++) {
        results[i] = _functionDelegateCall(address(this), data[i]);
    }
    return results;
}

(Nota: El error aquí discutido ha sido corregido en versiones posteriores del Multicall de OpenZeppelin.)

La Incompatibilidad: Conflicto entre ERC-2771 y Multicall

El núcleo de la vulnerabilidad del contrato inteligente del incidente ThirdWeb surgió de una inconsistencia crítica en la forma en que ERC-2771 y Multicall procesan el calldata. ERC-2771 espera que el reenviador de confianza empaquete juntos los datos del mensaje y la información del remitente. El contrato receptor utiliza entonces _msgData() y _msgSender() para desempaquetar correctamente esta información.

Sin embargo, la función Multicall, en su implementación vulnerable, no fue diseñada para ser compatible con la forma en que ERC-2771 empaqueta datos para las meta-transacciones. Específicamente, cuando Multicall procesa un lote de llamadas, debería haber extraído correctamente el _msgSender() de la meta-transacción inicial y luego haber añadido esta información del remitente al calldata de cada llamada individual antes de ejecutarlas. Este paso crucial estaba ausente.

Sin la información del remitente correctamente añadida al calldata dentro de cada sub-llamada procesada por Multicall, el contexto ERC-2771 dentro del contrato objetivo intentaría desempaquetar la información del remitente de los últimos 20 bytes del _msgData() de la sub-llamada. De manera crítica, un atacante podría controlar estos últimos 20 bytes. Esto permitió a un actor malicioso elaborar calldata específico que, cuando era procesado por Multicall e interpretado por un contrato habilitado con ERC-2771, ejecutaría lógica arbitraria con un valor _msgSender() manipulado (por ejemplo, una dirección controlada por el atacante o incluso la dirección del pool del propio protocolo). Esto efectivamente eludía las verificaciones de seguridad previstas y violaba las expectativas establecidas por ambas especificaciones, dando lugar a acciones no autorizadas.

Incidente ThirdWeb: Análisis del Ataque y Explotación

Examinemos un ejemplo del mundo real de la explotación de la vulnerabilidad del contrato inteligente del incidente ThirdWeb, utilizando una transacción de ataque analizada por la plataforma Phalcon de BlockSec.

La estrategia del atacante consistió en manipular el _msgSender() para hacerse pasar por un pool de Uniswap, vaciando así su balance de tokens.

  • Paso 1: Adquisición Inicial de Tokens. El atacante comenzó intercambiando 5 WETH por 3.455.399.346 tokens TIME en un exchange descentralizado. Esto proporcionó los tokens necesarios para la posterior manipulación.

  • Paso 2: Ejecución Maliciosa de Multicall. Este es el núcleo del exploit. El atacante invocó un reenviador de confianza con calldata cuidadosamente elaborado para explotar la incompatibilidad ERC-2771/Multicall. Cuando este calldata fue analizado por la función Multicall, resultó en la llamada a la función burn del contrato del token TIME. De manera crítica, debido a la vulnerabilidad, el _msgSender() fue interpretado incorrectamente como la dirección del Pool de Uniswap. Esto permitió al atacante quemar efectivamente una porción significativa de los tokens TIME en poder del pool de Uniswap, sin autorización real. La plataforma Phalcon de BlockSec proporciona trazado detallado de transacciones para visualizar este flujo.

    Traza de transacción que muestra el multicall malicioso
    Traza de transacción que muestra el multicall malicioso

    La imagen anterior ilustra cómo se procesa la llamada Forwarder.execute del atacante. La función multicall recibe un array de bytes, que luego conduce a la llamada de la función burn con el _msgSender() manipulado.

    Vista detallada del análisis de multicall y la llamada a la función burn
    Vista detallada del análisis de multicall y la llamada a la función burn

    Esta vista detallada de Phalcon muestra el bytes[] de longitud 1 siendo utilizado como datos para llamar al contrato, lo que conduce a la ejecución de la función burn bajo el falso _msgSender().

  • Paso 3: Manipulación del Precio. Al quemar una gran cantidad de tokens TIME del pool de Uniswap, el atacante redujo drásticamente la liquidez del pool para TIME. Esta escasez artificial provocó que el precio de TIME en relación con WETH se disparara dentro del pool.

  • Paso 4: Arbitraje Rentable. Con el precio de TIME artificialmente inflado, el atacante intercambió sus 3.455.399.346 tokens TIME restantes por 94 WETH, obteniendo una ganancia sustancial del precio manipulado.

Esta secuencia de eventos demuestra un ataque sofisticado que aprovecha una sutil vulnerabilidad en contratos inteligentes derivada de la incompatibilidad entre módulos.

Asegura tus Contratos Inteligentes con BlockSec

No dejes que las incompatibilidades ocultas expongan tu proyecto a riesgos. Nuestros auditores expertos realizan auditorías exhaustivas de contratos inteligentes para identificar y mitigar vulnerabilidades antes de que puedan ser explotadas.

El Mejor Auditor de Seguridad para Web3

Valida el diseño, el código y la lógica de negocio antes del lanzamiento

Conclusiones Clave y Lecciones del Incidente ThirdWeb

El incidente ThirdWeb sirve como un recordatorio crítico de las complejidades inherentes a la seguridad Web3, particularmente en lo que respecta a la interacción de bibliotecas de terceros.

  • Riesgos de Interoperabilidad: En el espacio DeFi en rápida evolución, los proyectos dependen en gran medida de una serie de bibliotecas y módulos de terceros. Si bien estos componentes aceleran el desarrollo, sus interacciones pueden introducir vulnerabilidades inesperadas y encubiertas. El incidente ThirdWeb ilustra claramente que incluso componentes ampliamente utilizados y aparentemente robustos como el ERC2771Context y MulticallUpgradeable de OpenZeppelin pueden crear brechas de seguridad críticas cuando su integración no se gestiona meticulosamente.
  • La Auditoría Técnica Profunda es Esencial: Este tipo de vulnerabilidad en contratos inteligentes no se detecta fácilmente mediante verificaciones superficiales. Requiere una profunda experiencia técnica para analizar cómo los diferentes módulos procesan e interpretan los datos, especialmente el calldata, e identificar posibles inconsistencias. Una auditoría exhaustiva de contratos inteligentes, centrada en las interacciones entre módulos y los casos límite, es fundamental.
  • Monitoreo Continuo y Respuesta a Incidentes: Incluso con auditorías robustas, pueden surgir nuevos vectores de ataque. El monitoreo continuo de seguridad en blockchain, como el que proporciona el Phalcon de BlockSec, es crucial para detectar actividad sospechosa en tiempo real y permitir una respuesta rápida ante incidentes para minimizar daños.
  • Más Allá de la Seguridad de los Módulos Individuales: Los desarrolladores deben pensar más allá de la seguridad de los componentes individuales y considerar la postura de seguridad holística de todo su sistema de contratos inteligentes. Cómo fluyen los datos entre los diferentes módulos, cómo se preservan o alteran los contextos y cómo se gestionan las llamadas externas son consideraciones críticas.

El incidente ThirdWeb subraya la importancia de un enfoque proactivo e integral de la seguridad en blockchain. Confiar únicamente en la reputación de las bibliotecas individuales es insuficiente; las interacciones entre ellas deben ser examinadas rigurosamente.

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit

Get Real-Time Protection with Phalcon Security

Audits alone are not enough. Phalcon Security detects attacks in real time and blocks threats mid-flight.

phalcon security