帖子
分享您的知识。
剖析 Sui 上的 Cetus 协议漏洞
2025年5月22日,一个针对Sui区块链上的Cetus协议的重大漏洞,估计造成2.23亿美元的损失. 由于所涉及的机制异常,该事件立即引起了整个生态系统的关注,尤其是技术观察家的关注. 接下来全面分析了从闪存交换和勾选操作到溢出检测逻辑中的静默漏洞的攻击.
https://suiscan.xyz/mainnet/tx/DVMG3B2kocLEnVMDuQzTYRgjwuuFSfciawPvXXheB3x
设置
攻击者通过使用 flash_swap 借用大量的 SUI 代币来换取 HasUI 来启动漏洞. 与传统的闪存贷款不同,Cetus中的flash_swap允许用户预先获得代币1(在本例中为SUI),然后在同一笔交易中偿还代币0(HasUI). 这种机制是攻击者设置的核心.
在这个特殊的例子中,攻击者成功获得了576万个SUI,并有义务偿还1002万个HasUI. 但是在此次互换中,流动性池中HasUI的价格受到严重操纵. 该矿池的价格从代表1.056的分笔成交点跌至如此之低以至于价格仅达到0.0000009977——大幅贬值至其原始价格的0.00009%.
与报价区间对应的价格区间为:
战略流动性注入
在这次价格暴跌之后,攻击者使用open_position创建了窄幅流动性头寸,选择了高度特定的报价区间(TickLower:300000,TickUpper:300200). 在这种被操纵的环境中,他们注入了天文数字的流动性:超过10^34个单位,都在分时暴跌造成的超压缩价格区间内.
这是由一个看似无害的函数实现的:get_amount_by_liquidity. 在正常情况下,此函数计算需要多少代币 A 和代币 B 才能匹配特定的流动性水平. 它使用诸如 get_delta_a 之类的辅助函数来实现此目的,它依赖于 get_sqrt_price_at_tick.
但是,由于操纵的当前即时报价为-138185,而且所选的分时报价范围远远超出该范围(从300000开始),get_amount_by_liquidity内部的逻辑路径确保了计算能够通过涉及左移操作(checked_shlw)的脆弱代码部分.
溢出和截断:核心漏洞
这就是漏洞真正成为技术性的地方. 函数 checked_shlw 本应处理 256 位数字向左移动 64 位. 在类似 Solidity 的环境中,这样的操作存在风险,因为它可能会溢出. 这个特殊的实现试图通过检查输入是否超过预定义的阈值来检测溢出:0xffffffffffffffffffffffff << 192.
检测 64 位安全偏移的实际阈值应为 2^ (256-64)-1. 但是,(0xfffffffffffffff << 192) 大于 2^192. 这意味着精心选择的输入可以通过低于代码中使用的阈值来绕过溢出检查,但仍然足够大,足以在执行期间造成溢出.
攻击者提供了这样的输入,流动性和价格差异的乘法无声地溢出,返回的值比预期的要小得多,实际上几乎为零.
结果,该协议计算出攻击者只需要支付少量代币 A(本质上是一个单位)即可为池中增加大量流动性. 这种错误的计算使攻击者能够在没有实际成本的情况下注入大量流动性.
随后,攻击者通过repay_flash_swap移除了增加的流动性,并通过repay_flash_swap支付未付的flash_swap代币完成了攻击. 攻击者获利了 5,765,124 个 SUI 和 10,024,321 个 HasUI. 最后,Cetus 团队通过两个 PR 修复了该漏洞:
https://github.com/CetusProtocol/integer-mate/pull/6/files
Cetus 很快在其 integer-mate 存储库上发布了一个补丁,第一个拉取请求试图完善溢出检测. 但是,最初的修复还不够. 它使用了 1 << 192 的掩码,这仍然允许边缘大小写值滑过.
接下来是第二次拉取请求,进行更严格的比较,检查输入是否大于或等于 2^192,从而确保适当的边界以安全地向左移动. 只有通过此更正,漏洞才得到有效缓解.
- Sui
根本原因不是 DeFi 机制中的逻辑错误,而是未能正确检测低级算术运算中的溢出行为
Sui is a Layer 1 protocol blockchain designed as the first internet-scale programmable blockchain platform.