本文分析了Abracadabra.money 的 Cauldron V4 合约被攻击事件,攻击者利用cook()
函数中的漏洞绕过了协议的最终偿付能力检查,从合约中窃取了约170万美元的MIM。文章深入探讨了漏洞的原理及其利用方式,还提出了可以避免此类事件的设计建议,并总结了该事件造成的后果以及协议方的反应。
Abracadabra 的这次攻击暴露了 Cauldron V4 批量处理逻辑中的一个严重缺陷,允许攻击者绕过偿付能力检查,并耗尽了 170 万美元的 MIM。这个技术分析解释了漏洞是如何运作的、它在链上的影响,以及 DeFi 构建者可以应用的设计经验来预防类似的漏洞。
漏洞利用
Abracadabra Hack Explained: $1.7M MIM Spell 第三个 CauldronV4 漏洞利用的解释
Abracadabra.money 是一个去中心化借贷平台,允许用户存入生息代币 (ibTKNs) 作为抵押品来借入 Magic Internet Money (MIM),一种与美元Hook的稳定币。最近的 abracadabra 攻击表明,当批量处理和路由逻辑包含细微缺陷时,接受生息抵押品的可组合系统是如何被利用的。通过接受 ibTKNs (例如 yVault 代币) 作为抵押品,该协议允许用户从产生收益的资产中解锁额外的流动性,否则这些资产将保持闲置状态。这种资本效率使 MIM Spell 成为 DeFi 生态系统中的核心构建块,尤其是在我们更广泛地关注 DeFi 货币市场 时,但同时也是一个复杂的构建块,其中分层集成和模块化设计为细微的逻辑风险留下了空间。
这正是为什么来自信誉良好的公司的全面 智能合约审计 仍然至关重要,尤其是在 abracadabra 攻击等事件之后,这些事件突出了依赖批量交易系统、预言机驱动的定价以及跨多个市场的抵押品核算的协议,其批量交易系统和复杂的抵押品核算可能会如何失效。
这是影响 MIM Spell 的第三起重大事件,之前的两次漏洞利用共同强调了模块化借贷系统的架构风险和 去中心化借贷 的机制。
虽然最近的事件导致了大约 170 万美元的损失,远小于第一次(约 649 万美元)和第二次(约 1300 万美元)事件,但它揭示了 Cauldron 路由器中的状态处理缺陷如何绕过偿付能力执行的另一个维度。
为了背景和连续性,我们强烈建议在深入研究本次事件之前,回顾之前的分析:
这些报告共同说明了小的架构疏忽,例如不正确的债务核算、延迟验证或未检查的路由器扩展逻辑,当与高资本可组合性结合时,可能导致严重的损失。
Abracadabra 通过建立在 BentoBox 技术上的模块化系统运行,该技术为其非托管 vaulting 和借贷机制提供了基础:
用户将抵押品存入 Cauldron,并根据预言机确定的抵押率借入 MIM。如果抵押品价值低于清算阈值,清算人可以偿还债务以获取抵押品,从而在市场上保持偿付能力。
这种模块化架构功能强大但要求很高:由于多个组件以原子方式交互,因此即使是单个标志管理不当或未检查的Hook也可能在系统中级联,正如一系列 MIM Spell 漏洞利用所证明的那样。对于构建跨链或路由流动性的团队,可以委托进行 区块链桥审计。
对于那些运行类似部署或分析 EVM 分叉的人,可以在我们的 Solidity 审计 中找到安全指导。此外,我们在 Three Sigma 提供 Rust/Solana 审计、Move 审计 和 dApp 前端审计,以解决特定于语言和层的漏洞。
有关 Abracadabra 的组件 (Cauldrons、DegenBox、预言机和清算路径) 如何交互的详细可视化,请参阅我们的第二次漏洞利用分析中包含的架构概述:
2025 年 10 月 4 日 UTC 时间 12:54:23,攻击者利用 Abracadabra.Money 的 Cauldron V4 合约耗尽了 ~1,793,755 MIM(Magic Internet Money,价值约 179 万美元),仅用了一笔交易(tx hash:0x842aae91c89a9e5043e64af34f53dc66daf0f033ad8afbf35ef0c93f99a9e5e6
)。该漏洞利用利用了 Cauldron cook()
函数中的一个缺陷,该缺陷允许绕过协议的最终破产检查。通过在一个 cook
调用中捆绑特定操作,特别是借款操作后跟恶意操作 ID 0,攻击者提取了一笔抵押不足的贷款,并避免了通常会阻止这种未经授权的借款的偿付能力检查。然后,被盗的 MIM 通过稳定币进行兑换,并转换为以太币。总的来说,攻击者从漏洞利用中获得了约 395 ETH,并立即将其提取到外部钱包,并通过 Tornado Cash 混合以混淆追踪。
该漏洞利用源于 Cauldron V4 cook()
实现的一个设计缺陷,该实现处理批量操作,但未能保存包含意外操作时的关键状态标志。以下是攻击者如何滥用此缺陷的深入技术分析。
cook()
函数Abracadabra 的 cook()
函数允许用户排队多个操作(例如添加抵押品、借款、还款等),以在一个原子交易中按顺序执行。通常,如果任何这些操作可能使贷款面临破产的危险(例如借款或移除抵押品),则会设置一个标志 needsSolvencyCheck
,并且最终检查会在最后运行,以确保用户保持偿付能力。下面显示了相关的代码片段(为清楚起见已简化):
在预期的逻辑中,每当借入贷款时,ACTION_BORROW
(ID 5) 都会设置 status.needsSolvencyCheck = true
(类似地,移除抵押品也会这样做)。在循环结束时,如果此标志保持为真,则合约会调用偿付能力检查以恢复任何使用户抵押不足的交易。但是,该代码还允许通过 Cauldron V4 中的 _additionalCookAction
Hook添加未在基本合约中定义的其他操作 ID,主要用于支持特殊 Cauldrons 中的扩展功能(例如 GMX 市场操作)。在默认实现中,任何无法识别的 action
都会进入最后的 else
分支,该分支调用存根 _additionalCookAction
并返回默认的 CookStatus(false, false)
,这意味着不需要偿付能力检查。这是关键错误:处理未知操作的行为会重置 CookStatus
结构,从而清除先前借款设置的 needsSolvencyCheck
标志。
攻击者利用了这一点,通过使用操作序列 [5, 0]
制作了一个 cook
调用,即先借款,然后是虚拟操作 0。
操作 5 (ACTION_BORROW) 成功地将 MIM 借到了攻击者的地址,并设置了破产检查标志。
然后,操作 0 (不是标准操作) 触发了回退逻辑,该逻辑擦除了 CookStatus
。
在基本 CauldronV4
合约中,_additionalCookAction
已定义但为空(没有实现)。
调用未实现的 virtual 会在 solidity 中产生默认的零值:
returnData
→ bytes("")
returnValues
→ 0
returnStatus
→ CookStatus(false, false)
status
变为 CookStatus(false, false)
,将 hasAccrued
和 needsSolvencyCheck
都覆盖为 false
。
循环之后,代码检查:
由于 status.needsSolvencyCheck == false
(它已被返回的 CookStatus
重置),因此不执行 require
,并且借入的资金保持转移出去,而没有操作后的偿付能力验证。
换句话说,当 cook()
退出循环时,合约认为没有发生任何危险操作。因此,最终的偿付能力检查 if (status.needsSolvencyCheck)
被完全跳过,尽管贷款使账户严重资不抵债,但协议并未恢复。状态已更新以记录新的债务,Cauldron 的攻击者的 userBorrowPart
增加,并且将 MIM stablecoins 铸造到他们的地址,但通常的不变性未生效。下面的屏幕截图说明了状态更改:MIM 代币从 Abracadabra 的 DegenBox(vault)转移到攻击者,没有引发错误。
攻击者在多个钱包中重复了此 cook([5,0]) 技巧,以在规避每个地址的借款限制的同时,最大限度地提高利润。六个不同的攻击者控制的地址各自调用了该漏洞,每个地址借款约 300,000 MIM(总计约 180 万 MIM)。
在耗尽 Cauldron 合约的流动资金后,攻击者合并了被盗的 MIM,并将其兑换为更稳定的资产,最终兑换为 ETH:
这些兑换利用聚合 DEX 路线以最大限度地减少滑点,将被盗的稳定币转换为总计 ≈395 ETH。最后,攻击者将约 395 ETH 提取到外部拥有的地址。链上分析显示,ETH 在不久后被转移到 Tornado Cash 中,从而打破了资金与漏洞利用之间的联系。
所有六个漏洞利用交易都发生在同一区块时间范围内。在团队意识到问题后,Cauldron 合约立即暂停。
Abracadabra CauldronV4 漏洞利用源于逻辑缺陷,而不是缺少访问控制或预言机问题。因此,预防需要强大的内部一致性检查和用于 cook()
中批量处理逻辑的更安全的设计模式。以下是可能阻止此事件发生的关键防御策略。
needsSolvencyCheck
标志一个深层设计级别的修复方法是使偿付能力检查在单个 cook()
执行中 不可重置。
当前的实现使用:
这会完全重置该结构。相反,更新应保留先前设置的标志:
这样,一旦借款或抵押品移除操作将交易标记为有风险,即使其他操作返回 false,后续操作也无法覆盖该标志。
虽然批量处理很方便,但它会将风险集中到单个执行后检查中。
在每次借款或抵押品移除操作后引入内联偿付能力检查(而不是将所有检查推迟到最后)可以消除漏洞利用路径。
示例模式:
这保证了不变性强制执行,而与后续操作无关,从而确保在没有立即进行偿付能力验证的情况下,不会发生任何借款。
但是,这种方法确实存在权衡:
在实践中,理想的解决方案是在安全性和灵活性之间取得平衡,例如,仅对高风险操作(借款、取款、杠杆)强制执行内联偿付能力检查,同时允许低风险操作(还款、添加抵押品、应计利息)保持批量处理。
MIM (Magic Internet Money) 是一种稳定币,针对 Cauldron 市场内过度抵押的头寸进行铸造。用户存入抵押品,借入 MIM,并根据汇率和协议参数管理健康状况。
批量操作路由器中的逻辑缺陷允许攻击者绕过最终的偿付能力检查,从而实现抵押不足的借款和通过交换进行的快速提取。
严格验证操作 ID,对承担风险的步骤强制执行每次操作的偿付能力检查,并确保像 needsSolvencyCheck
这样的标志无法在同一批处理中稍后清除。
是的,每个堆栈都有独特的陷阱。像 Solidity 审计 这样的深入审查有助于发现特定于 EVM 的排序错误(例如,批量路由器、委托调用模式、精度损失)。
非 EVM 链具有不同的内存、签名者和 tx 模型。有针对性的 Rust/Solana 审计 侧重于帐户模型滥用、CPI 边界和租金/所有权检查,这些检查在 EVM 上不存在。
Move 的资源语义可以防止某些类型的错误,但会引入其他错误(功能、模块升级)。专门的 Move 审计 验证资源安全性、访问控制和升级脚本。
网络钓鱼和 UX 错误签名可能与合约错误一样具有破坏性。dApp 前端审计 检查钱包提示、域完整性、RPC/提供商流程和签名表面,以减少用户级别的妥协。
此概述可帮助非安全团队评估适合性、范围和方法:什么是智能合约审计以及如何选择合适的安全合作伙伴。
是的,路由器错误配置、清算边缘案例、价格来源假设和未经检查的“扩展Hook”会再次出现。有关模式的摘要,请参阅 2024 年顶级 DeFi 漏洞利用和常见漏洞。
我们之前的两次分析:
该漏洞利用针对的是一个较旧、流动性较低的 CauldronV4 部署,该市场在攻击发生时已基本不再积极使用。这个特定的 Cauldron 仍然在链上处于活动状态,但 TVL 极小,这解释了为什么总损失仅为约 170 万美元,远低于之前的 649 万美元和 1300 万美元的事件。
由于易受攻击的合约仍然可以公开访问但处于非活动状态,因此它有效地充当了未监控的攻击面。尽管该设计缺陷在 cook()
实现中已经存在了几个月,但影响仅受仍存放在该旧版 Cauldron 中的少量抵押品基础的限制。
易受攻击的 Cauldron 合约于 2023 年 2 月 18 日 UTC 时间 03:37:47 部署。截至 2025 年 10 月 6 日,这意味着该合约已存在 961 天,大约 2 年 7 个月。
在此期间,有缺陷的 _additionalCookAction
回退逻辑一直保持在生产环境中,未被注意到和修补。由于此分支在活跃市场中很少被调用,因此该问题一直处于休眠状态,直到攻击者在此旧版 Cauldron 部署中专门针对它。
参考:合约源代码 / 验证代码,https://etherscan.io/address/0x692887E8877C6Dd31593cda44c382DB5b289B684#code
影响较小(约 170 万美元)的主要原因是:
虽然架构隔离阻止了级联效应,但可利用的旧版部署的存在强调了为什么即使是不活跃的合约也应该在被取代后正式弃用和暂停。
- 原文链接: threesigma.xyz/blog/expl...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!