适得其反 —— 任意地址欺骗攻击解析

This article is not available in the current language yet. Showing the original version.
建议项目方在编写代币合约时不要同时使用 Multicall 和 ERC2771Context。

By: 九九


背景


2023 年 12 月 5 日,Web3 基础开发平台 thirdweb 表示在预构建智能合约中发现了安全问题,所有使用预构建智能合约部署的 ERC20、ERC721、ERC1155 代币均受到了影响。(具体受影响的合约代码版本可以参考:https://blog.thirdweb.com/security-vulnerability/)



根据慢雾安全团队情报,在 2023 年 12 月 7 号,ETH 主网上的 Time 代币正是因为该漏洞遭受到攻击,攻击者获利约 19 万美金。目前仍有不少存在漏洞的代币合约正在被攻击,慢雾安全团队第一时间介入分析,并将结果分享如下:


前置知识


1. ERC-2771 是元交易的标准。用户可以将交易的执行委托给第三方 Forwarder,通常称为中继器或转发器。


通常合约中直接调用者的地址是使用 msg.sender 获取的,但在使用了 ERC-2771 的情况下,如果 msg.sender 是转发器角色的话,那么会截断传入的 calldata 并获取最后 20 个字节来作为交易的直接调用者地址。



2. Multicall 是一个智能合约库,其作用是允许批量执行多个函数调用,从而减少交易成本。这个库通常用于优化 DApp 的性能和用户体验,特别是当需要进行多个读取操作时。


从代码中可以看到,thirdweb 项目存在漏洞的合约使用的 Multicall 库是通过循环调用 DelegateCall 函数来执行引用了该库的合约中的其他函数。


 

根本原因


漏洞的根本原因是代币合约同时使用了 ERC-2771 和 Multicall 库。攻击者通过 Forwarder 合约的 execute 函数调用代币合约的 multicall 函数,执行合约中的其他函数(如燃烧代币)。这种方式成功通过了 ERC-2771 的 isTrustedForwarder 判断,最终将函数的调用者解析为恶意 calldata 的最后 20 个字节。因此,攻击者成功欺骗了合约,使其误认为调用者是其他用户的地址,进而导致燃烧了其他用户的代币。


攻击步骤分析


此处以攻击交易 0xecdd11...f6b6 为例进行分析:


1. 攻击者首先用 5 个 WETH 在 Uniswap V2 池子中兑换成 345,539,9346 枚 Time 代币。


 

2. 接着调用 Forwarder 合约的 execute 函数,构造恶意的 data 去调用代币合约的 multicall 函数,此时代币合约会根据攻击者传入的恶意 data 去 delegateCall 执行代币合约的 burn 函数,燃烧掉池子地址中的 62,227,259,510 枚 Time 代币。



3. 由于上一步 burn 掉了池子中大量的 Time 代币,使得 Time 代币的价格被瞬间拉高,所以攻击者最后可以反向 swap 第一步获取的 Time 代币,掏空了池子中的 94 枚 WETH。



攻击原理剖析


在 Forward 合约的 execute 函数中,验证 req.from 的签名过后会用 call 交互 req.to(代币地址)。其中攻击者传入的 req.data 为




因为 0xac9650d8 为 multicall 函数的函数签名,故会调用代币合约的 multicall 函数,并且multicall 函数传入的 data 值为 0x42966c680000000000000000000000000000000000000000c9112ec16d958e8da8180000760dc1e043d99394a10605b2fa08f123d60faf84。


为什么传入 multicall 函数的 data 值中没有 req.from 呢?这是因为 EVM 底层处理 call 调用时会根据其中的偏移量而截断所需要的值,而攻击者传入的 calldata 值中设定偏移量是 38,数值长度为 1,所以刚好截取出来的 data 值是42966c680000000000000000000000000000000000000000c9112ec16d958e8da8180000760dc1e043d99394a10605b2fa08f123d60faf84。



具体可以参考 EVM opcode 中对 call 的描述(https://www.evm.codes/?fork=shanghai)。



由于 0x42966c68 为 burn 函数的函数签名,所以会根据攻击者构造的 data 值去 delegatecall 调用代币合约的 burn 函数。



其中 _msgSender() 函数被 ERC-2771 库重写。



由于 multicall 是通过 delegatecall 进行调用的,所以 isTrustedForwarder 传入的 msg.sender 其实是 Forward 合约的地址,从而通过了判断,最终导致 _msgSender() 返回的值为传入的 calldata 的最后 20 个字节,即池子的地址 0x760dc1e043d99394a10605b2fa08f123d60faf84。

结论


本次攻击的根本原因在于合约同时引用了 Multicall 和 ERC2771Context,攻击者可以在转发请求中插入恶意 calldata,利用 Multicall 的 delegatecall 功能来通过受信任转发器的判断,并操纵子调用中 _msgSender() 的解析,从而可以操控任意用户的代币。


慢雾安全团队建议项目方在编写代币合约时,不要同时使用 Multicall 和 ERC2771Context,如果预期需求需要同时引用的话,则必须检查 calldata 长度是否符合预期或使用 openzeppelin 官方最新版本的 Multicall 和 ERC2771Context 合约。


参考


攻击者地址:0xfde0d1575ed8e06fbf36256bcdfa1f359281455a


攻击合约:0x6980a47bee930a4584b09ee79ebe46484fbdbdd0


相关攻击交易:https://etherscan.io/tx/0xecdd111a60debfadc6533de30fb7f55dc5ceed01dfadd30e4a7ebdb416d2f6b6


受影响的版本详情:https://blog.thirdweb.com/security-vulnerability/


缓解工具:https://mitigate.thirdweb.com/


往期回顾

慢雾:朝鲜黑客 Telegram 定点欺诈攻击分析

每月动态 | Web3 安全事件总损失约 3.49 亿美元

双重流动性之殇 —— KyberSwap 巨额被黑分析

谨防受骗 | 假冒慢雾(SlowMist) 网站分析

慢雾(SlowMist) 与新火科技(SINOHOPE) 达成战略合作,共建 Web3 安全基础设施

慢雾导航


慢雾科技官网

https://www.slowmist.com/


慢雾区官网

https://slowmist.io/


慢雾 GitHub

https://github.com/slowmist


Telegram

https://t.me/slowmistteam


Twitter

https://twitter.com/@slowmist_team


Medium

https://medium.com/@slowmist


知识星球

https://t.zsxq.com/Q3zNvvF

Share to:

Author: 慢雾科技

Opinions belong to the column author and do not represent PANews.

This content is not investment advice.

Image source: 慢雾科技. If there is any infringement, please contact the author for removal.

Follow PANews official accounts, navigate bull and bear markets together
PANews APP
US stocks closed mixed, with COIN falling more than 3.05%.
PANews Newsflash