网络第5域

适得其反:代币合约任意地址欺骗攻击解析

字号+作者: 来源:安全内参 2023-12-08 00:00 评论(创建话题) 收藏成功收藏本文

ETH 主网上的 Time 代币正是因为该漏洞遭受到攻击,攻击者获利约 19 万美金。目前仍有不少存在漏洞的代币合约正在被攻击。By: 九九背景2023 年 12 月 5 '...

ETH 主网上的 Time 代币正是因为该漏洞遭受到攻击,攻击者获利约 19 万美金。目前仍有不少存在漏洞的代币合约正在被攻击。

By: 九九XzE品论天涯网

XzE品论天涯网

背景

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

XzE品论天涯网

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

XzE品论天涯网

前置知识

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

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

XzE品论天涯网

XzE品论天涯网

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

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

XzE品论天涯网

XzE品论天涯网

XzE品论天涯网

根本原因

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

XzE品论天涯网

攻击步骤分析

此处以攻击交易 0xecdd11...f6b6 为例进行分析:XzE品论天涯网

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

XzE品论天涯网

XzE品论天涯网

XzE品论天涯网

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

XzE品论天涯网

XzE品论天涯网

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

XzE品论天涯网

XzE品论天涯网

攻击原理剖析

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

XzE品论天涯网

XzE品论天涯网

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

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

XzE品论天涯网

XzE品论天涯网

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

XzE品论天涯网

XzE品论天涯网

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

XzE品论天涯网

XzE品论天涯网

其中 _msgSender() 函数被 ERC-2771 库重写。XzE品论天涯网

XzE品论天涯网

XzE品论天涯网

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

结论

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

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

参考

攻击者地址:0xfde0d1575ed8e06fbf36256bcdfa1f359281455aXzE品论天涯网

XzE品论天涯网

攻击合约:0x6980a47bee930a4584b09ee79ebe46484fbdbdd0XzE品论天涯网

XzE品论天涯网

相关攻击交易:https://etherscan.io/tx/0xecdd111a60debfadc6533de30fb7f55dc5ceed01dfadd30e4a7ebdb416d2f6b6XzE品论天涯网

受影响的版本详情:https://blog.thirdweb.com/security-vulnerability/XzE品论天涯网

XzE品论天涯网

缓解工具:https://mitigate.thirdweb.com/XzE品论天涯网

XzE品论天涯网

本网除标明“PLTYW原创”的文章外,其它文章均为转载或者爬虫(PBot)抓取; 本文只代表作者个人观点,不代表本站观点,仅供大家学习参考。本网站属非谋利性质,旨在传播马克思主义和共产主义历史文献和参考资料。凡刊登的著作文献侵犯了作者、译者或版权持有人权益的,可来信联系本站删除。 本站邮箱[email protected]