您现在的位置:kastop>> Kas信息 Kastop聚焦>>正文内容

横跨一个月的跨链攻击:Allbridge 被黑分析

作者:九九,慢雾科技

背景

2026 年 8 月 19 日,知名跨链桥项目 Allbridge 遭到攻击,损失约 19 万美元。然而本次攻击却横跨接近一个月才完成,以下是慢雾安全团队针对此次攻击事件的具体分析:

前置知识

为了理解这次攻击,我们需要先理解 Circle 的 CCTP 协议和其跨链消息传递系统。

CCTP 是 Circle 的跨链转账协议。它的基本做法是,在源链销毁 USDC,在目标链重新铸造同等数量的 USDC。这样可以避免桥接合约凭空增加余额。

正常的 CCTP 转账通常按下面的步骤进行:

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

Circle 的 MessageTransmitterV2 是负责传递消息的合约。它会对完整消息出具 attestation,也就是 Circle 对指定的跨链消息进行签名证明。但是这个证明只能说明消息内容经过 Circle 认证,不能单独说明消息里写的金额已经真实发生转移。目标链的 Circle TokenMessengerV2 负责铸币。MessageTransmitterV2 收到消息后,会根据消息头里的 recipient 找到要回调的合约。正常的 CCTP 消息会把这个地址设为目标链的 TokenMessengerV2 合约。它接着检查源端 TokenMessenger、代币、金额和接收地址,检查通过后才铸造 USDC。Allbridge 的 CCTP 模块则处在这条流程的后面。它要把已经完成的入金整理成 Router 能识别的记录,Router 再把代币转给用户。到这里有个需要特别注意的地方:

attestation 有效,不代表在源链实际发生过代币燃烧,不代表目标链已经执行了代币铸造,也不能代表 Router 已经真的收到对应 USDC。

至此我们可以知道,Circle 的 sendMessage 是通用接口。任何人都可以调用它,填写一段跨链消息内容,让 Circle 对这段内容进行认证。调用这个接口本身不会自动销毁 USDC,也不会自动铸造 USDC。正常的 CCTP 转账还需要源链的 TokenMessenger 参与。它会先销毁 USDC,再生成带有燃烧代币信息的消息。而在本次攻击中,攻击者只构造了跨链消息,绕过了销毁 USDC 这一步。

根本原因

在 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 转出代币。

攻击步骤分析

1. 2026 年 7 月 26 时,攻击者先提前在 Polygon 上直接调用 Circle MessageTransmitterV2 合约的 sendMessage 函数。这是一笔通用跨链消息发送操作,交易产生了 MessageSent 事件,但实际没有发生 USDC 销毁操作。Circle 随后会对完整消息签发 attestation,这一步是按协议预期设计正常执行。

消息被填成了 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。

这笔余额属于等待转给真实用户的跨链资金,攻击者等到了这极短的等待时机,真实入金发生后六秒,开始执行正式攻击交易。

3. 攻击合约会先调用 CCTPTokenMessenger 合约的 receiveCctpMessage 函数,传入 Polygon 交易中取得的消息和签名数据 attestation,其中 destinationCaller 检查和 sourceSender 检查均被通过(均由攻击者控制构造)。随后调用 Circle MessageTransmitterV2 合约的 receiveMessage 函数,在该函数中根据消息头的 recipient 回调攻击合约。攻击合约直接返回成功,并没有执行预期 Circle TokenMessenger 合约的铸造代币操作。而 Allbridge 也没有再次确认 Router 余额,也没有检查被回调的目标合约是否等于 Circle TokenMessengerV2,直接就把 amount - feeExecuted 写入 receivedMessages[messageHash],生成了一笔 1,000,000 USDC 的内部 credit。

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

5. 攻击者随后调用 Router 的 receiveToken 函数处理收款结算。Router 根据调用参数先再计算一次 hash,得到的值与 hookData 里攻击者先前早已计算构造好的 messageHash 值相同。接着只检查 CCTPTokenMessenger 合约中的该 messageHash 对应的 receivedTokenAmount 记录是否大于零,就视为已经收到真实入金代币。由于 Router 需要收 0.1% 的手续费,所以在扣除手续费后将剩余的 999,000 USDC 直接转给攻击合约。

整个过程中 Router 只检查 CCTPTokenMessenger 合约中的 credit 是否存在,而并不会再次确认这笔 credit 是否对应链上同等规模的资产真实到账。

6. 攻击者窃取到 999,000 USDC 后,向 Aave 归还 808,844 USDC 本金和约 404.422012 USDC 闪电贷手续费。最终留下约 189,751.554381 USDC,完成攻击获利。这笔交易把 Router 的 191,156 USDC 基本清空。损失的主要部分来自刚刚到达、尚未转给用户的真实跨链入金。

有趣的是,Router 在上面所收取的 1,000 USDC 费用,这笔钱后来被其他攻击者复刻相同的攻击手法给取走。

总结

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

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

1. 消息头中的 sender 参数必须对应受信任的源端组件合约;2. 消息头中的 recipient 参数必须限制为目标链的 Circle TokenMessengerV2 合约;3. 只有在 Router 的 USDC 余额确实被铸造增加后才能建立可兑现的入金记录。

对跨链桥系统来说,最重要的是被合理认证检查的消息是跨链结算的必要条件,真实的资产到账才是 Router 最终付款的依据。



感动 同情 无聊 愤怒 搞笑 难过 高兴 路过
【字体: 】【收藏】【打印文章】 【 打赏 】 【查看评论

相关文章

    没有相关内容