Autor: Nueve Nueve

Edición: 77

Antecedentes

El 19 de agosto de 2026, el conocido proyecto de puente entre cadenas Allbridge sufrió un ataque, con una pérdida de aproximadamente 190.000 dólares. Sin embargo, este ataque tardó casi un mes en completarse. A continuación se presenta un análisis detallado del equipo de seguridad SlowMist sobre este incidente:

Conocimientos previos


Para entender este ataque, primero debemos comprender el protocolo CCTP de Circle y su sistema de mensajería entre cadenas.


CCTP es el protocolo de transferencia entre cadenas de Circle. Su funcionamiento básico es: destruir USDC en la cadena de origen y acuñar de nuevo una cantidad equivalente de USDC en la cadena de destino. Así se evita que los contratos del puente aumenten el saldo por generación de forma artificial.
正常的 CCTP 转账通常按下面的步骤进行:


源链 TokenMessenger 销毁 USDC
  -> Circle MessageTransmitter 认证并转发消息
  -> 目标链 Circle TokenMessenger 接收消息
  -> TokenMessenger 进行验证后铸造 USDC
  -> 等 Router 看到真实到账后再把 USDC 转给用户


MessageTransmitterV2 de Circle es un contrato responsable de transmitir mensajes. Emitirá una attestation para el mensaje completo; es decir, una prueba de firma de Circle del mensaje entre cadenas especificado. Sin embargo, esta prueba solo indica que el contenido del mensaje fue autenticado por Circle; no puede demostrar por sí sola que el importe escrito en el mensaje ya haya ocurrido realmente una transferencia.

TokenMessengerV2 de Circle en la cadena destino es responsable de acuñar. Después de que MessageTransmitterV2 reciba el mensaje, encuentra el contrato que debe ser llamado de vuelta según el recipient del encabezado del mensaje. Un mensaje CCTP normal establecerá esta dirección como el contrato TokenMessengerV2 en la cadena destino. Luego verifica el TokenMessenger de la cadena origen, el token, el monto y la dirección de recepción; solo después de pasar estas verificaciones se acuña USDC.

El módulo CCTP de Allbridge se encuentra después de este flujo. Debe organizar el depósito que ya se completó en un registro que el Router pueda reconocer; luego el Router transfiere los tokens al usuario. En este punto hay un aspecto que se debe tener especialmente en cuenta: que la attestation sea válida no significa que en la cadena origen haya ocurrido realmente la quema de tokens, no significa que en la cadena destino ya se haya ejecutado la acuñación de tokens, y tampoco puede significar que el Router realmente haya recibido el USDC correspondiente. Con esto podemos saber que el sendMessage de Circle es una interfaz general. Cualquiera puede llamarla, completando un contenido de mensaje entre cadenas, para que Circle autentique ese contenido. Llamar a esta interfaz en sí no destruye automáticamente USDC ni acuña automáticamente USDC. Una transferencia CCTP normal aún requiere la participación del TokenMessenger en la cadena origen: primero destruye USDC y luego genera un mensaje que incluye la información del token quemado. En este ataque, el atacante solo construyó un mensaje entre cadenas, evitando ese paso de destrucción de USDC.

Causa raíz


在 Allbridge 的 CCTPTokenMessenger 合约中,接收跨链消息的 receiveCctpMessage 函数缺少对 CCTP 消息头中 sender 字段是否与远端 TokenMessenger 相等的检查,recipient 字段也没有检查是否等于 Circle 的 TokenMessengerV2 合约,导致 MessageTransmitterV2.receiveMessage 会把转发的跨链消息交给攻击合约来判断代币是否铸造成功,由于在本合约中没有再检查 Router 的 USDC 余额在记账前是否是真实增加的,合约直接信任了攻击者构造的消息中的金额,最终将其记账成可付款余额(跨链消息的 hookData 中 messageHash 对应的 receivedTokenAmount 数值)。

此次在 hookData 中也没有提供任何检查保护。Router 在执行付款时会根据调用参数重新计算 messageHash,然后再查询这个 hash 先前所记录的内部入金余额。而攻击者可以在 Polygon 发消息之前,离线算好同一组参数对应的 hash,再把 messageHash 放进直接放入跨链消息的 hookData 中。这样一来,匹配的是攻击者自己创建好的内部记录,和真实资产结算无关。
因此攻击者可以在 Polygon 上直接调用MessageTransmitterV2.sendMessage 构造任意跨链消息,并等 Circle 对其签名后,使得 Base 链的 attestation 验证成功,该伪造消息被当作真实跨链收款,最终触发 Router 转出代币。

Análisis de los pasos del ataque


1. El 26 de julio de 2026, el atacante primero llamó con antelación directamente a la función sendMessage del contrato Circle MessageTransmitterV2 en Polygon. Esta es una operación general de envío de mensajes entre cadenas; la transacción generó el evento MessageSent, pero no ocurrió ninguna operación de destrucción de USDC. Circle posteriormente emitirá una attestation para el mensaje completo; esta etapa se ejecuta normalmente según lo diseñado por el protocolo.

消息被填成了 CCTP 风格的数据。源域是 Polygon,目标域是 Base,声明金额为 1,000,000 USDC,feeExecuted 为零,destinationCaller 指向 Allbridge 的 CCTPTokenMessenger 合约。攻击者把消息头 recipient 设置为自己的合约,把消息正文中的 sourceSender 设置成配置里的远程 Messenger 地址,还把提前算好的 Router messageHash 放进 hookData,方便后续验证使用。


2. 这条恶意跨链消息创建后攻击者等待了约 24 天。因为 Base Router 是一个转发路由,平时不会长期持有大额流动性。直到 2026 年 8 月 19 日 这天,Allbridge relayer 刚把一笔由其他用户真实 CCTP 入金的 USDC 铸造到 Router,金额约为 191,112 USDC,Router 余额达到约 191,156 USDC。


Este saldo pertenecía a fondos entre cadenas en espera de ser transferidos al usuario real. El atacante aprovechó esa ventana de espera extremadamente corta: seis segundos después de que ocurriera el depósito real, comenzó a ejecutar la transacción de ataque formal.

3. El contrato de ataque primero llamará a la función receiveCctpMessage del contrato CCTPTokenMessenger, pasando el mensaje y los datos de firma attestation obtenidos en la transacción de Polygon; en destinationCaller y en la comprobación de sourceSender, ambas se pasan (todas son construidas y controladas por el atacante). Luego llama a la función receiveMessage del contrato MessageTransmitterV2 de Circle, donde esta función hace un callback al contrato del atacante según el recipient del encabezado del mensaje. El contrato de ataque devuelve directamente éxito, sin ejecutar la operación esperada de acuñación del contrato Circle TokenMessenger. Además, Allbridge tampoco vuelve a confirmar el saldo del Router, ni verifica si el contrato de destino que se llama de vuelta es igual al Circle TokenMessengerV2; simplemente escribe amount - feeExecuted en receivedMessages[messageHash], generando un credit interno de 1,000,000 USDC.

4. 由于攻击者先前创建的跨链消息中构造的目标金额是 1,000,000 USDC,而 Router 当时大约只有 191,156 USDC,所以攻击者先通过 Aave 闪电贷为 Router 提供 808,844 USDC,让余额暂时达到攻击者在假消息中声明的金额,满足后续的代币转出操作。

5. El atacante llama luego a la función receiveToken del Router para gestionar la liquidación del cobro. El Router recalcula primero el hash de acuerdo con los parámetros de la llamada; el valor obtenido es igual al messageHash que el atacante ya había calculado y construido previamente en hookData. Luego solo verifica si el registro receivedTokenAmount asociado con ese messageHash en el contrato CCTPTokenMessenger es mayor que cero y, con eso, lo considera como un token de depósito real recibido. Debido a que el Router cobra una tarifa del 0.1%, después de deducir la tarifa transfiere el resto de 999,000 USDC directamente al contrato del atacante.
Durante todo el proceso, el Router solo comprueba que exista el credit en el contrato CCTPTokenMessenger, pero no vuelve a confirmar si ese credit corresponde a una llegada real de activos en cadena de escala equivalente.

6. Tras robar los 999,000 USDC, el atacante devuelve a Aave el principal de 808,844 USDC y la tarifa del préstamo flash de aproximadamente 404.422012 USDC. Finalmente quedan alrededor de 189,751.554381 USDC, con lo que se completa el lucro del ataque. Esta transacción prácticamente vacía los 191,156 USDC del Router. La mayor parte de la pérdida proviene de los depósitos de entrada reales entre cadenas que llegaron recientemente y que aún no se habían transferido a los usuarios.


Curiosamente, la tarifa de 1,000 USDC cobrada por el Router en lo anterior, más tarde fue sustraída por otro atacante que replicó la misma técnica de ataque.

Resumen

这次攻击事件的核心问题是 Allbridge 缺少对跨链消息合理性的检查。Circle 的 attestation 只能证明消息内容没有被篡改,并不能证明跨链消息真实触发过代币的燃烧或铸造操作。Allbridge 直接信任 CCTPTokenMessenger 消息中攻击者自行构造的金额、资金来源地址、和 messageHash,并记录成了可兑现的余额,把它当作真实的入金数量。

慢雾安全团队建议项目方修复时需要同时守住三条边界:

1. El parámetro sender del encabezado del mensaje debe corresponder al contrato de componentes de origen de confianza;
2. El parámetro recipient del encabezado del mensaje debe limitarse al contrato Circle TokenMessengerV2 de la cadena de destino;
3. Solo se puede establecer un registro de depósito canjeable después de que el saldo de USDC del Router realmente se haya incrementado por la acuñación.

Para los sistemas de puentes entre cadenas, lo más importante es que el mensaje que se autentica y verifica de manera razonable sea una condición necesaria para la liquidación entre cadenas; la llegada real de activos es el fundamento final del pago del Router.