漏洞描述
burnFrom函数的作用是供被授权用户操作授权用户的资产,而在操作授权用户授权的资产时需要同步更新授权用户的资产数量,即销毁授权用户特定数量的资产,同时需要更新代币总量以及授权转账的额度,同时burnFrom函数应该具备溢出检查逻辑设计或者使用SafeMath函数进行溢出防御,而不少合约中缺乏allowance更新操作,甚至存在下溢问题、特权后门等。
漏洞示例
下图所示burnfrom函数在销毁代币时只做了授权数量的检查,而在授权转账之后未更新授权转账的额度导致被授权用户可以无限制的销毁授权账户的资产
漏洞演示
Step 1:下载合约源代码到本地并使用Remix进行部署调试
https://cn.etherscan.com/address/0xa8ba4095833a3f924d86cb3941099c1abb75ea13
部署操作:
Step 2:查询当前合约owner所持资产数量
Owner地址:0x5B38Da6a701c568545dCfcB03FcB875f56beddC4
所持资产:500000000000000000
数值精度:18
Step 3:使用合约的owner地址向用户A和用户B分别转账,为后期测试做准备
用户A地址:0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2
转账数量:100000000000000000
用户B地址:0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB
转账数量:100000000000000000
Step 4:使用A账户地址给B账户授权转账数量20000000000000000
Step 5:由于合约中的burnFrom函数存在设计缺陷,在销毁授权用户特定数量的资产时,未更新授权转账的额度,导致被授权账户可以无限制销毁授权账户的资产,下面我们使用B账户来销毁A账户的资产,销毁数量为之前A账户授权给B账户的额度——20000000000000000
当下A账户资产数量如下:0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2
通过进行销毁操作:
检查授权额度:
之后检查A账户资产:100000000000000000——>80000000000000000
由于授权额度未更新,所以此时B用户依旧可以销毁A用户的资产数量,下面我们再一次进行销毁:
再次查看授权额度——依旧未变:
查看A账户的资产数量:80000000000000000——60000000000000000
依次类推,可知授权用户B可以销毁被授权用户A所有的资产
安全建议
采用OpenZeppelin官方标准
https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Burnable.sol
原创文章,作者:七芒星实验室,如若转载,请注明出处:https://www.sudun.com/ask/34367.html