Back to Blog

~$16M Perdidos: DxSale, SquidRouterModule y Más | BlockSec Semanal

Code Auditing
June 3, 2026
11 min read
Key Insights

Durante la semana pasada (2026/05/25 - 2026/05/31), BlockSec identificó múltiples incidentes de ataques en varios ecosistemas de blockchain. La tabla a continuación lista 5 incidentes destacados con pérdidas totales estimadas de aproximadamente $16M.

Fecha Incidente Tipo Pérdida Estimada
2026/05/27 SquidRouterModule Validación de Entrada Incorrecta ~$3.2M
2026/05/29 Stake DAO Clave Privada Comprometida ~$91K*
2026/05/29 DxSale Lógica de Negocio Incorrecta y Compromiso de Clave ~$7.3M
2026/05/30 Gravity Bridge Proceso de Firma Off-chain Vulnerable ~$5.4M
2026/05/30 Alephium Proceso de Firma Off-chain Vulnerable ~$300K*

*Notas adicionales:

  • En el incidente de Stake DAO, el atacante comprometió la clave privada del deployer y la utilizó para reconfigurar el par OFT v2 de LayerZero en el contrato vsdCRV en Arbitrum, lo que permitió acuñar 5.4 billones de vsdCRV. Debido a la liquidez limitada en los DEX, solo se retiraron aproximadamente $91K antes de que los pools se agotaran.
  • En el incidente de Alephium, más allá de los aproximadamente $300K en activos de custodia del puente drenados (USDT, USDC, WETH, WBTC en Ethereum y USDT, WBNB en BNB Chain), el atacante también acuñó 13.7M de wALPH sin respaldo en Ethereum. El puente fue cerrado, lo que impidió al atacante canjear o transferir estos tokens de vuelta a través del puente de Alephium.

Se seleccionan dos incidentes para un análisis en profundidad:

  • SquidRouterModule: Al igual que el exploit de CrossCurveFi, repitió la misma clase de error de integración, mostrando cómo bifurcar lógica cross-chain sin una comprensión profunda y una revisión de seguridad rigurosa puede convertir rápidamente la complejidad heredada en riesgo heredado.
  • DxSale: Su prolongada línea de tiempo del ataque demuestra que los contratos heredados sin explotar no son necesariamente seguros, y que los protocolos deben monitorear continuamente la actividad on-chain y off-chain, minimizar el acceso privilegiado y nunca confundir años de silencio con prueba de seguridad.

El Mejor Auditor de Seguridad para Web3

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

Destacado de la Semana: DxSale

Este incidente fue seleccionado como el destacado de la semana porque la combinación de un contrato locker sin parchear con años de antigüedad y una clave de deployer comprometida ilustra un patrón recurrente: los protocolos que tratan el código del tiempo de despliegue como permanentemente seguro, sin auditoría continua ni rotación de privilegios, conllevan un riesgo oculto que puede ser aprovechado en cualquier momento.

El 29 de mayo de 2026, DxSale, una plataforma de venta de tokens y bloqueo de liquidez en BNB Chain, fue explotada [1] por aproximadamente $7.3M. La función de retiro de tokens contenía tres actualizaciones de estado faltantes que permitían a cualquier usuario con una posición de bloqueo válida retirar repetidamente y drenar todo el pool compartido, sin necesidad de privilegios de propietario. Un compromiso separado de la clave del deployer de DxSale a través de la delegación EIP-7702 no era un requisito previo para el exploit, pero amplificó la eficiencia del atacante al permitir la manipulación de tarifas y bloquear a otros usuarios de crear nuevos bloqueos.

Antecedentes

DxSale es una plataforma de venta de tokens y bloqueo de liquidez en BNB Chain. Su componente DxLock permite a los desarrolladores de proyectos bloquear tokens LP en bóvedas con bloqueo temporal, brindando garantías a los inversores de que la liquidez no puede ser retirada de forma maliciosa (rug-pull).

El mecanismo de bloqueo principal funciona de la siguiente manera: un usuario deposita tokens en el contrato locker, creando un registro de bloqueo indexado por la combinación de la dirección del llamante y un ID de token. Cada registro almacena si el bloqueo existe, si los tokens están actualmente bloqueados, el monto bloqueado, la marca de tiempo de desbloqueo y la dirección del token. Cuando el período de bloqueo expira, el usuario llama a unlockToken(tokenId) para retirar sus tokens.

Dado que el locker mantiene tokens de muchos usuarios simultáneamente en un saldo compartido, las asignaciones individuales deben rastrearse con precisión a través de registros de bloqueo separados. La seguridad de todo el pool depende de que cada retiro valide correctamente el registro propio del llamante y lo actualice después de la transferencia.

Análisis de Vulnerabilidad

La función unlockToken en el contrato con errores (0xeb3a...e449) contenía tres defectos compuestos, cada uno siendo una actualización de estado o verificación faltante:

function unlockToken(uint256 tokenId) public nonPayable {
    require(_increaseLockTime[msg.sender][tokenId].field0_0_0);  // locker exists
    require(_increaseLockTime[msg.sender][tokenId].field0_1_1);  // tokens are locked
    require(_increaseLockTime[msg.sender][tokenId].field2);       // amount > 0

    if (block.timestamp > _increaseLockTime[msg.sender][tokenId].field3) {
        _increaseLockTime[msg.sender][tokenId].field0_1_1 = 0;
    }

    v0, v1 = _increaseLockTime[msg.sender][tokenId].field5_0_19.balanceOf(this);
    require(v1 >= _increaseLockTime[msg.sender][tokenId].field2);
    v2, v3 = _increaseLockTime[msg.sender][tokenId].field5_0_19.transfer(
        msg.sender, _increaseLockTime[msg.sender][tokenId].field2
    );
}
  1. Sin aplicación del período de bloqueo. El período de bloqueo estaba protegido por una sentencia if en lugar de un require. Al llamarse antes de la marca de tiempo de desbloqueo, la función simplemente omitía borrar la bandera de bloqueo en lugar de revertir. Esto significaba que los tokens podían retirarse en cualquier momento, independientemente del período de bloqueo.

  2. El monto bloqueado nunca se pone a cero. Después de transferir tokens al llamante, la función no ponía a cero field2 (el monto bloqueado). Cada llamada posterior leía el mismo valor original y retiraba la misma cantidad nuevamente, creando un bucle de retiro infinito.

  3. Verificación de saldo compartido en lugar de asignación individual. La llamada balanceOf(this) verificaba el saldo total de tokens del contrato en lugar de la asignación individual del llamante. Un llamante con una posición de bloqueo pequeña podía drenar todo el pool compartido mientras el contrato aún mantuviera suficientes tokens totales.

En conjunto, estas tres actualizaciones de estado faltantes eliminaron todas las condiciones de salida de la función: la llamada nunca revertía prematuramente, el monto del retiro nunca disminuía y la verificación de saldo nunca bloqueaba hasta que el contrato estuviera completamente vaciado. El error era explotable por cualquier usuario que creara una posición de bloqueo; no se requerían privilegios de propietario para el drenaje principal.

Análisis del Ataque

La cuenta del deployer de DxSale (0x47bacf93), operando a través de la delegación EIP-7702, había exhibido actividad anómala desde el 2026-04-15, incluyendo transferencias masivas de propiedad, cambios de tarifas y operaciones de desbloqueo de LP en múltiples contratos de DxSale. El 2026-05-26, el deployer transfirió la propiedad del contrato locker víctima (0xeb3a...e449) al contrato del atacante (0xc457...fa69). Dos días después, el atacante ejecutó un drenaje en cinco pasos.

El siguiente análisis se basa en una transacción representativa 0x437b26...c1b303.

  • Paso 1: El atacante intercambió BNB por tokens BNBC en PancakeSwap y proporcionó liquidez para crear un nuevo par Cake-LP (BNBC/WBNB), recibiendo aproximadamente 0.323 tokens LP.

  • Paso 2: Usando los privilegios de propietario obtenidos a través de la transferencia de propiedad previa, el atacante llamó a changeFees(1) para establecer la tarifa de creación de bloqueo en 1 wei, luego llamó a createLocker para depositar los aproximadamente 0.323 tokens LP en una nueva posición de bloqueo (tokenId=131). Inmediatamente después, el atacante llamó a changeFees(10^36) para elevar la tarifa a un valor astronómico, impidiendo que otros usuarios crearan nuevos bloqueos.

  • Paso 3: El atacante llamó a la función de exploit (0x11b432b4), que orquestó llamadas repetidas a unlockToken en una sola transacción. A través de múltiples transacciones, el atacante drenó sistemáticamente el locker: 0x437b26...c1b303 drenó 161.4 tokens LP mediante tokenId=131, 0x82f541...a9fa73 y 0x5dd61f...4298aa drenaron posiciones de bloqueo adicionales, y 0xac8f5e...d36df9 drenó 260.3 tokens LP mediante tokenId=319 a través de 478 llamadas.

  • Paso 4: El atacante llamó a removeLiquidity en PancakeSwap para convertir los tokens LP drenados de vuelta en sus tokens subyacentes (BNBC y WBNB).

  • Paso 5: El atacante intercambió los tokens subyacentes por WBNB y BUSD a través de PancakeSwap y transfirió las ganancias a direcciones externas. BSCScan registró 123,447 transacciones durante 4 días (2026-05-28 al 05-31) para este contrato atacante.

Conclusión

La causa raíz de este incidente son las tres actualizaciones de estado faltantes en unlockToken. Cada una tiene una solución directa: aplicar el período de bloqueo con require en lugar de if, poner a cero el monto bloqueado después de cada retiro y verificar la asignación individual del llamante en lugar del saldo total del contrato. Estos defectos por sí solos eran suficientes para la explotación; cualquier usuario que creara una posición de bloqueo podía drenar todo el pool compartido mediante llamadas repetidas, sin necesidad de privilegios de propietario.

El compromiso previo del deployer de DxSale a través de la delegación EIP-7702 no era un requisito previo para el exploit, pero amplificó la eficiencia del atacante. Al transferir la propiedad y manipular las tarifas, el atacante creó posiciones de bloqueo de costo casi nulo y bloqueó a los usuarios legítimos de crear bloqueos competidores. En el aspecto operativo, los protocolos deben auditar continuamente los contratos heredados, especialmente aquellos que mantienen fondos de usuarios, y evitar la custodia de funciones de administración con una sola clave. Años de operación sin incidentes no validan la seguridad del código no auditado.

Referencias

  • [1] Anuncio de DxSale

Comienza con Phalcon Explorer

Sumérgete en las Transacciones para Actuar con Sabiduría

Pruébalo gratis ahora

Más Incidentes de Esta Semana

SquidRouterModule

El 27 de mayo de 2026, un contrato desconocido llamado SquidRouterModule fue explotado [1] en Ethereum debido a una validación de entrada incorrecta, resultando en aproximadamente $3.2M en pérdidas. La causa raíz fue un uso incorrecto de la integración de Axelar Bridge, similar al patrón de ataque anterior de CrossCurveFi [2]. El contrato no validó correctamente los mensajes cross-chain a través del Axelar Gateway, lo que permitió al atacante falsificar payloads que autorizaban e intercambiaban los tokens de las víctimas en pools maliciosos preconstruidos. Una dirección de atacante separada que había desplegado el token falso y sembrado los pools eliminó posteriormente la liquidez para extraer los activos reales. Este ataque afectó a 86 carteras Safe. A pesar de su nombre, el SquidRouterModule no fue construido, desplegado ni operado por el equipo del protocolo Squid [3].

Antecedentes

El contrato es un módulo de servicio de intercambio cross-chain diseñado para la cartera Safe, construido sobre el protocolo cross-chain de Axelar. El contrato proporciona la función expressExecuteWithToken, que soporta la ejecución anticipada de transacciones antes de la confirmación de mensajes cross-chain. Los usuarios deben pre-autorizar los permisos APPROVE y SWAP del contrato en su cartera Safe antes de usar este servicio. Cuando se llama a expressExecuteWithToken, el contrato decodifica las instrucciones de operación en el payload y llama al execTransactionFromModule de la cartera Safe para ejecutar operaciones de autorización de tokens e intercambio.

Análisis de Vulnerabilidad

La función _executeWithToken en el contrato vulnerable (0x1f1d...23ca) solo verificaba si srcAddress era igual a la constante squidRouter. Sin embargo, srcAddress es un parámetro proporcionado por el llamante, mientras que squidRouter es una cadena inmutable que cualquiera puede leer del contrato. Esto permitía al atacante eludir trivialmente la verificación y ejecutar la función _processPayload con contenido de payload arbitrario.

En contraste, la función executeWithToken del Squid Router legítimo llama a gateway.validateContractCallAndMint() y revierte con NotApprovedByGateway() si la red de validadores de Axelar no ha confirmado la transacción.

El contrato vulnerable no aplicaba ninguna autorización de gateway en la ruta expressExecuteWithToken. Combinado con los permisos APPROVE y SWAP que los usuarios de la cartera Safe habían pre-autorizado al módulo, los payloads falsificados podían operar directamente sobre los fondos de las víctimas.

Análisis del Ataque

El siguiente análisis se basa en la transacción 0xd29d1c...3bb854.

Antes del ataque, una dirección de atacante separada desplegó un token falso (0xe6Ff...3512) y creó múltiples pools de Uniswap V3, cada uno emparejando el token falso con un token valioso diferente (por ejemplo, USDC, ENA, USDT), sembrando los pools con liquidez del token falso.

  • Paso 1: El atacante falsificó calldata malicioso y llamó a la función expressExecuteWithToken del contrato vulnerable, usando la dirección conocida de squidRouter como sourceAddress para eludir la verificación de validación. A través de los permisos APPROVE y SWAP que la víctima había pre-autorizado al módulo, el payload falsificado forzó aprobaciones de tokens desde la cartera Safe de la víctima hacia el pool de Uniswap.

  • Paso 2: Usando estas aprobaciones forzadas, el payload intercambió los tokens de la víctima por el token falso sin valor a través del pool malicioso correspondiente.

El atacante repitió este método a través de múltiples transacciones, apuntando a un total de 86 carteras Safe que habían autorizado el contrato vulnerable. La dirección de atacante separada que había desplegado el token falso y sembrado los pools eliminó posteriormente la liquidez para extraer los activos reales, obteniendo finalmente una ganancia de aproximadamente $3.2M.

Conclusión

Este incidente fue causado por una validación de entrada incorrecta en la ruta de manejo de mensajes cross-chain. La única verificación de seguridad dependía de un parámetro controlable por el llamante comparado con una constante de lectura pública, sin proporcionar protección real. Combinado con los permisos APPROVE y SWAP pre-autorizados de los usuarios de la cartera Safe, el atacante podía falsificar mensajes cross-chain y robar fondos de usuarios.

El incidente es similar al exploit de CrossCurveFi [2]: ambos involucran integraciones de Axelar Bridge que no lograron validar correctamente los mensajes cross-chain entrantes. Al integrar infraestructura de mensajería cross-chain, el contrato de destino debe validar de forma independiente la autenticidad del mensaje a través del mecanismo de autorización del puente. Omitir esta validación y depender de entradas controlables por el atacante convierte la integración en una superficie de ataque abierta.

Referencias

  • [1] Alerta de Phalcon: exploit de SquidRouterModule
  • [2] Alerta de Phalcon: patrón de ataque de CrossCurveFi
  • [3] Aclaración de Squid Router

Comienza con Phalcon Security

Detecta cada amenaza, alerta sobre lo importante y bloquea ataques.

Pruébalo gratis ahora

Acerca de BlockSec

BlockSec es un proveedor integral de seguridad blockchain y cumplimiento de criptomonedas. Desarrollamos productos y servicios que ayudan a los clientes a realizar auditorías de código (incluyendo contratos inteligentes, blockchain y carteras), interceptar ataques en tiempo real, analizar incidentes, rastrear fondos ilícitos y cumplir con las obligaciones AML/CFT, a lo largo de todo el ciclo de vida de protocolos y plataformas.

BlockSec ha publicado múltiples artículos de seguridad blockchain en conferencias prestigiosas, reportado varios ataques de día cero en aplicaciones DeFi, bloqueado múltiples hackeos para rescatar más de 20 millones de dólares y asegurado miles de millones en criptomonedas.

Best Security Auditor for Web3

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

BlockSec Audit