起因#
看到推友发推文,提及某智能合约中的严重漏洞。
流程分析#
攻击者批量调用合约的 VOTEToken()
函数,实现凭空创建大量 VOTETRUMP
代币,然后将 VOTETRUMP
代币通过 Uinswap
兑换为 ETH
,实现套利。
漏洞分析#
正巧最近在参与Solidity 殘酷共學 (DeFiHackLabs x WTF Academy),在课程的第 11 讲:构造函数和修饰器有这样的描述:
注意:构造函数在不同的 Solidity 版本中的语法并不一致,在 Solidity 0.4.22 之前,构造函数不使用 constructor 而是使用与合约名同名的函数作为构造函数而使用,由于这种旧写法容易使开发者在书写时发生疏漏(例如合约名叫 Parents,构造函数名写成 parents),使得构造函数变成普通函数,引发漏洞,所以 0.4.22 版本及之后,采用了全新的 constructor 写法。
而查看合约代码可以看到合约使用的 Solidity
版本是 ^0.4.11
,是低于 0.4.22
。 这意味着该合约的构造函数定义遵循旧版规则。
构造函数错误:合约名称为 VeritaseumToken,而实际定义的构造函数名为 VOTEToken。由于二者不一致,VOTEToken 函数并未被识别为构造函数,而是成为了一个普通的公共函数。此外,函数没有使用任何可见性修饰符,因此任何人都可以随意调用它,并通过调用该函数将其账户的 VOTETRUMP 代币余额增加到代币的最大供应量。
这种设计失误为攻击者创造了条件,他们通过调用 VOTEToken () 函数铸造出大量 VOTETRUMP 代币,并最终在去中心化交易所中套利。
修复漏洞#
- 升级 Solidity 版本:首先,建议将 Solidity 版本升级至 0.4.22 或更高版本,以使用 constructor 关键字定义构造函数。这可以避免由于构造函数名称拼写错误而引发的漏洞。
- 修正构造函数定义:如果无法升级合约代码版本,必须确保构造函数名称与合约名称一致。在这个案例中,应该将 VOTEToken () 改为 VeritaseumToken ()。
- 添加适当的权限控制:即使使用旧版构造函数定义,仍需为重要函数添加适当的权限控制(如 onlyOwner 修饰器),避免任何用户可以调用这些函数进行代币铸造。
警示#
此漏洞提醒我们,在使用低版本的 Solidity 编写合约时,必须严格遵循构造函数命名规则,避免因为拼写错误引发的严重安全问题。同时,对于任何涉及代币铸造、转移等关键操作的函数,都应引入权限控制机制,以防止恶意用户滥用合约漏洞。
此外,在设计合约时,建议使用最新稳定版本的 Solidity,以确保利用新特性和修复已知漏洞,从而提升合约的安全性。