ERC1155 NFT代币中的TotalSupply不一致漏洞解析

本文详细分析了ERC1155 NFT代币中totalSupply字段不一致的安全漏洞,该漏洞会影响依赖总供应量进行计算的项目。文章涵盖漏洞原理、影响范围和修复方案,涉及重入攻击和智能合约安全实践。

ERC1155 NFT代币中的TotalSupply不一致问题

2021年11月1日,我们向OpenZeppelin报告了一个漏洞:在ERC1155 NFT代币中,totalSupply可能显示得比实际值低。这会影响依赖totalSupply进行计算的项目,例如在投票或确定市值时。所有使用v4.3.2之前ERC1155Supply.sol扩展的代币都会受到影响。该漏洞已于11月12日迅速修复并公开披露。我们要感谢Francisco Giordano领导的OpenZeppelin团队在此问题上的出色合作和快速响应。

背景 — ERC1155内部机制

ERC1155代币实现了"多代币标准",单个合约可以同时处理同质化(类似ERC20)和非同质化(类似ERC721)代币。该标准允许创建具有唯一ID的非同质化代币,但每个代币可以有多个实例,使它们之间可以互换。

EIP-1155标准不需要在智能合约层面跟踪同质化代币的totalSupply,并建议项目通过跟踪事件来记录代币总数。虽然这对某些用例有效,但其他用例需要在链上知道发行的代币总量。为方便这一点,OpenZeppelin提供了一个名为ERC1155Supply.sol的ERC1155扩展,它将ERC20代币中熟悉的totalSupply字段添加到ERC1155代币中。该字段在代币铸造或销毁时更新。

ERC1155的另一个功能是允许通知代币接收者,这可以在可组合的以太坊生态系统中实现有趣的用例。缺点是控制流被交给不可信的第三方,允许臭名昭著的重入攻击。因此,每个处理ERC1155代币(和ERC712代币)的项目都必须小心防范这些攻击。

ERC1155Supply漏洞详解

以下代码片段展示了铸造新代币所涉及函数的简化视图:

1
2
3
4
5
ERC1155首先在beforeTokenTransfer(第12行)中进行一些检查,
然后将新代币铸造给接收者(第14行),
接收者被允许进行接受检查(第17行)。
接受检查在第29行通过调用接收者智能合约的onERC1155Received实现
将控制流交给接收者。

ERC1155Supply通过首先调用ERC1155铸造方法然后增加totalSupply来添加总供应量跟踪。这里的关键部分是在totalSupply增加之前,控制流作为正常ERC1155铸造的一部分被交给接收者。在这个阶段,攻击者已经拥有代币,例如可以用于投票,但totalSupply尚未增加,可能允许攻击者假装拥有比实际应得份额更高的代币比例(包括拥有大于totalSupply的份额,如果应用程序假设totalSupply <= balance[any_user],这可能导致其他攻击)。从技术上讲,这是一种轻量级重入攻击形式,因为攻击者只会重新进入totalSupply视图函数而不修改任何状态。这通常被视为"良性重入",但在这种情况下可能导致实际攻击。

应对措施

要使攻击可被利用,铸造函数必须被不可信的接收者调用。虽然这对于动态可铸造代币通常是这种情况,但请注意,当代币通常不铸造给不可信接收者但桥接到侧链(如Polygon)时,也可能发生这种情况。在这种情况下,从以太坊到侧链的代币转移通常会触发侧链上EIP1155合约的铸造。

如果您负责实现ERC1155Supply的ERC1155代币,请考虑升级到新发布的OpenZeppelin v4.3.3或更新版本。如果无法升级,请向文档添加警告,让集成商了解此安全公告。

如果您负责处理实现ERC1155Supply扩展的ERC1155代币平台,并且允许任何人铸造,您不能再依赖这些代币的totalSupply,需要准备替代实现。

任何使用OpenZeppelin或其他常用库的项目都应确保在智能合约安全注册表中报告使用的库,并确保其安全联系信息是最新的。

如果您持有受此漏洞影响的ERC1155代币,无需立即采取行动,只要您的代币未在易受此攻击的平台中使用,它们就是安全的。如果您不确定平台的安全性,请提取您的代币并联系平台,要求他们确认是否对此漏洞安全。

关于我们

ChainSecurity的使命是在区块链生态系统中建立信任,使这项新兴技术能够在成熟组织、政府和区块链公司中发挥其潜力。

如果您有任何问题,请随时通过contact@chainsecurity.com联系我们(包括审计请求),或通过help@chainsecurity.com咨询有关此漏洞或其他漏洞的问题。也可访问chainsecurity.com。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计