#9 1inch事件:从Calldata损坏到伪造结算:链上二进制漏洞利用持续

#9 1inch事件:从Calldata损坏到伪造结算:链上二进制漏洞利用持续

2025年3月5日,一个集成了1inch Fusion V1协议的第三方解析器合约遭受了协同攻击,导致总损失超过500万美元。根本原因是结算流程中的不安全 Calldata 重构,攻击者控制的交互长度触发了后缀组装期间的指针下溢,从而允许注入伪造的结算数据。一种错误的信任边界进一步促成了此次攻击:解析器合约仅凭 msg.sender 就隐式信任结算合约转发的所有 Calldata,导致攻击者控制的数据尽管通过了所有访问控制检查,却继承了结算级别的权限。

此次事件之所以成为2025年最复杂的 DeFi 攻击之一,并非因为它利用了新颖的金融原语,而是因为它利用了低级的 ABI 和内存布局假设,模糊了智能合约漏洞与经典二进制漏洞之间的界限。

背景

1inch Fusion V1 协议

1inch 是一个去中心化交易所(DEX)聚合器,它跨多个 DEX 获取流动性,为用户提供优化的交易执行。1inch Fusion 构建在聚合器的限价订单基础设施之上,引入了一种基于荷兰式拍卖的订单匹配模型,允许用户指定灵活的执行参数,例如价格范围和交易时间窗口。

在 Fusion 模型中,用户订单不直接由协议本身完成。相反,它们由称为解析器的专业参与者执行。解析器可以被视为特权的、已列入白名单的参与者:要获得资格,它们必须质押代币以获得足够的 Unicorn Power,这是一种经济性准入门槛机制。

在操作层面,解析器运行自己的链下基础设施,与 1inch 的后端 API 交互,以发现用户订单并确定何时以及是否完成它们。一旦解析器决定执行订单,它会通过一个专用账户向结算合约提交一个链上交易,由该合约执行实际的交易。 (虽然 Fusion 涉及解析器之间竞争性的荷兰式拍卖,但此机制对于理解攻击并非必需,因此在此省略;为简化起见,我们假设解析器可以直接满足用户的订单条件。)

在执行交易时,解析器可以通过从外部市场获取流动性以提供优于用户最低要求的执行,或者直接使用自己的资产结算交易。在此过程中产生的任何盈余价值都将作为利润归于解析器。本文讨论的攻击针对的就是这样一个解析器合约。具体来说,是一个用于链上做市的合约,该合约持有资产并已授予结算合约批准,最终导致这些资产的损失。

订单处理和履行

1inch Fusion 中的订单执行由结算合约协调,并遵循一种由交互数据驱动的递归结算模型,而不是线性执行流程。

该过程始于解析器调用 settleOrders() 函数,传入编码第一个订单及其交互负载的 Calldata。结算合约不尝试一次性结算所有订单,而是通过重复调用内部 _settleOrder() 函数来增量处理它们。

对于每个订单,_settleOrder() 函数会在内存中重构一个对限价订单协议(AggregationRouterV5.fillOrderTo())的调用。在此重构过程中,结算合约将额外的解析器相关上下文以动态后缀的形式附加到交互数据中。此后缀包含执行元数据,例如解析器身份和累计费用,并且被限价订单协议视为不透明。它会被原封不动地转发,稍后在交互回调期间由结算合约自身解码。

订单完成后,控制权通过 fillOrderInteraction() 函数返回到结算合约。根据交互数据,结算合约要么通过递归调用 _settleOrder() 函数并传入剩余的交互负载继续结算,要么进入最终确定阶段。在最终阶段,结算合约通过调用解析器合约的 resolveOrders() 函数将控制权转发给解析器合约,并传入累积的执行上下文。

此设计允许在单个交易中顺序结算多个订单,同时将特定于解析器的逻辑推迟到所有协议级别的执行步骤完成后。

漏洞分析

漏洞源于内部 _settleOrder() 函数中不安全的 Calldata 重构逻辑,特别是在将动态后缀附加到交互数据期间。

解析器合约受显式访问控制保护:它们要求调用来自结算合约,并且在解析期间提供的解析器地址与解析器合约本身匹配。这些检查假定通过结算过程传播的解析器身份已正确构造且保持不变。此假设取决于解析器相关数据在 Calldata 重构期间如何编码和附加的正确性。

在结算过程中,_settleOrder() 会在内存中重构 Calldata,并附加一个包含解析器特定执行上下文的动态后缀。此后缀不仅包括解析器地址,还包括解析器依赖于解释结算合法性的订单相关信息。后缀被写入计算为 ptr + interactionOffset + interactionLength 的内存位置,其中 interactionLength 直接从 Calldata 读取,作为完整的 32 字节值。

由于此偏移量计算是在没有边界检查的情况下执行的,因此攻击者可以控制 interactionLength 以触发算术溢出并操纵后缀在内存中的写入位置。通过这样做,攻击者可以替换预期的后缀,并使用伪造的后缀,提供任意解析器地址以及攻击者控制的订单上下文。

结果是,当结算流程稍后解码后缀时,它可能会将执行解释为源自合法解析器并涉及有效订单数据,尽管这两个假设都不成立。攻击者实际上能够通过冒充解析器来注入自己的订单后缀版本,用几个 wei 交换数百万。

攻击分析

以交易 ++0x74bc++ 为例。攻击始于创建五个有效订单,这些订单交换了微不足道的代币数量(几个 wei)以换取不成比例的大量输出金额。这些订单在语法上是有效的,并且通过了协议级别的检查。

然后,攻击者使用大片空字节填充订单 Calldata。此填充用作一个受控的内存区域,稍后由于后缀放置不正确而将被覆盖。

至关重要的是,攻击者为最终订单指定了一个无效的 interactionLength 值。该值选择为 0xffff…fe00,当解释为有符号整数时,对应于 -512。由于 interactionLength 被视为一个无符号 256 位值并直接用于指针算术,这会在计算后缀写入偏移量时导致算术溢出。

下面的恶意交互结构被视为后缀:

总结

此次事件针对的是集成到 1inch 已弃用的 Fusion V1 协议中的第三方解析器合约,导致了巨额损失,这突显了几项重要教训。

  • 不安全的数据假设:依赖于动态构造的输入数据的系统,在任何部分受用户影响时,都不得假设其长度、偏移量或结构完整性。
  • 隐式信任链:当合约依赖上游组件来维护关键上下文,而不是在每个边界进行验证时,安全检查可能会被破坏。
  • 遗留攻击面:支持过时的组件会增加攻击面,并使协议更容易受到新颖的利用技术的影响。
  • 跨域利用模式:当涉及低级内存或数据布局逻辑时,传统软件中常见的漏洞可能会在链上重现。

参考

  1. https://blog.decurity.io/yul-calldata-corruption-1inch-postmortem-a7ea7a53bfd9
  2. https://paragraph.com/@cookies-research/1inch-fusion-cost-efficient-mev-resistant-swaps
  3. https://blog-zh.1inch.com/fusion-swap-resolving-onchain-component/#steps-5-6

关于 BlockSec

BlockSec 是一家全栈区块链安全和加密合规提供商。我们构建产品和服务,帮助客户在协议和平台的整个生命周期中进行代码审计(包括智能合约、区块链和钱包)、实时拦截攻击、分析事件、追踪非法资金,并履行 AML/CFT 义务。

BlockSec 在顶级会议上发表了多篇区块链安全论文,报告了 DeFi 应用的多次零日攻击,阻止了多次黑客攻击挽救了超过 2000 万美元,并保障了数十亿美元的加密货币。

Sign up for the latest updates