TransferMint 漏洞详解:超20个波场合约存无限增发代币风险

近日,PeckShield 安全人员分析发现,TRON 部分合约中存在致命缺陷,可被攻击者用来无限增发代币,进而扰乱正常的市场秩序,且部分DApp代币已经上线交易所,存在进一步的安全风险。

PeckShiled安全人员深入分析认为,这是一种名为 TransferMint  的新型漏洞,其后果可导致 TRC20 代币无限增发。 这一漏洞与 PeckShield 在 2018 年 Ethereum 平台上发现的例如  batchOverflow, proxyOverflow, transferFlaw, ownerAnyone 等漏洞特征相似又不同,受灾主体为各个 TRC20 代币。

经PeckShield统计,当前 Tron 平台上共有 20+ 个 DApp 或者智能合约代币面临这一漏洞的影响,PeckShiled 安全人员在发现问题的第一时间通过相关项目方重视这一漏洞的危害,包括但不限于 Iseri Project, RockstarToken,同时通知相关交易所暂停受影响代币的充值业务。

本次受影响的智能合约部分地址如下:

Contract Address
TUYVZudnCQq8y6JjL65FhLQYDurpQ4NBD2
TSmd4ku6DJXHuXadNsxERMgcZQdu6MPJXm
TAcDiVjMK1Ch3VJeMzmFnH1RoYrnEYDPyt
TC6o5RdXrvSQGtCedYja1KvnZTtSy681uS
TCxTmkY4q2pNYrNV6zLHJWvsbZtYXqDTjN
TDFd3ShioizhsHqTdSZSfhYRxtdXBvCJCN
TMTHXUTLRksDhFFd694uYvkYxRL68UdezX
TAs5gCuGtQyhu822CG3CgsKX8Afs2aPtRv
TZ4uWjo43gDEfpG5vtPgtN2JxzppryBubn
TP4vE9qxphZ37Njniw6NPZspFUD1eT2xRs
TB2SqC48afC9FX36bPQQHatoKo5m79JXKL
TYFP5hNf3vQCAZo6TmnGTaAZHRABRQKisW
TRu6xUwGHHRHDW3cGED2RsCMABByEinWn5
TYkb8p83JgqKndTLLsypH9Z81VWc4Gifzn
TGUCrYGGzb8D6uBiyMHAR5EVRAuJAXoqpB
TJYd7Nqj3o7ZWveKVtZ4uG1vRNKSmci4JE
TTAxUH77DDxg62JnaosPYfZMBSnXuy6aWR
TNhYmahDUBAoUTtRrUFRPmnYwDCFiLMyVw
...


其中 TNhYmahDUBAoUTtRrUFRPmnYwDCFiLMyVw TJYd7Nqj3o7ZWveKVtZ4uG1vRNKSmci4JE 为之前 Tron 平台上的『明星项目』TronCrush 的合约地址,援引 BCSEC TronCrush 智能合约存在造币漏洞,攻击者凭空创造巨量 TCC 代币 的文章说明:

这是一个上线前被大量 TRON Dapp KOL 宣传力推的项目,在第一次分红之前,被 Kiwi 进行上币交易,其无奈之下,主动联系 TRON 生态下头部的去中心化交易所 Trontrade 进行上币。之前由于做足了预热,3 月 26 号首日挖矿流水惊人的突破了 12 亿 TRX,由于挖矿的狂热,该项目方多次暂停游戏进行维护,27-28 日的交易量受此影响有所下滑,来到第一个分红日 29 号 12 点前夕。TronTrade 突然暂停了代币 TCC 的交易,似乎出现了一些问题,TronCrush 官方声称似乎代币 TCC 的智能合约存在 bug,正在检查中,但是尚未暂停游戏。

攻击原理分析:

 Tron TRC20 是一种与 Etherum ERC20  兼容的代币合约,其合约接口如下:

contractTRC20Interface{
   functiontotalSupply() publicconstantreturns(uint);
   functionbalanceOf(addresstokenOwnerpublicconstantreturns(uintbalance);
   functionallowance(addresstokenOwneraddressspenderpublicconstantreturns(uintremaining);
   functiontransfer(addresstouinttokenspublicreturns(boolsuccess);
   functionapprove(addressspenderuinttokenspublicreturns(boolsuccess);
   functiontransferFrom(addressfromaddresstouinttokenspublicreturns(boolsuccess);

   eventTransfer(addressindexedfromaddressindexedtouinttokens);
   eventApproval(addressindexedtokenOwneraddressindexedspenderuinttokens);
}

其中 transfer(address to, uint tokens) 为代币转让函数,从函数发起方向 to 地址转让 tokens 个 TRC20 代币,对于具体的 TRC20 代币实现方,其内部逻辑会有些许差异。

上述受影响的智能合约中,只有部分开源在 Github 上面,此处以开源的 Iseri-project 原始合约为例,详细漏洞细节披露如下:

TransferMint 漏洞详解:超20个波场合约存无限增发代币风险

上述 _transfer(address _from, address _to, uint256 _value) 函数在合约执行代币转账时被调用到,其内部逻辑如下:

  1. 确保代币转入方地址 _to 不为 0, 若不满足则直接退出;

  2. 获取代币转出方 _from 余额 oldFromVal

  3. 确保待转让金额 _value > 0,同时 oldFromVal >= _value,若不满足任一条件则直接退出;

  4. 获取 _to 余额 oldToVal

  5. 计算 _to 转入之后的余额,即 newToVal = oldToVal + _value

  6. 确保 newToVal > oldToVal

  7. 计算 _from 转出之后剩余金额,即 newFromVal = oldFromVal - _value

  8. 保存 _from 当前余额为 newFromVal

  9. 保存 _to 当前余额为 newToVal

  10. 检查转出方与转入方新旧余额总和相等,即 (oldFromVal + oldToVal) == (newFromVal + newToVal) 确保不会有整数溢出现象发生。

对于正常的两两转账操作而言,上述逻辑不会出现问题,但是当转账的转出转入方为同一地址时,上述代码存在致命漏洞,重点关注下面两行代码:

TransferMint 漏洞详解:超20个波场合约存无限增发代币风险

_from_to 为同一地址时,第 81 行的代码被第 82 行重写了,因此转账完成之后,_from 的余额即为 newToVal 的值,而 newToVal == oldToVal + _value == oldFromVal + _value

balances[_from] = oldFromVal + _value 。

因此 _from 的余额在转账完成之后会增加 _value 数量,从而达到自行发币的目的,也即这一漏洞命名为 TransferMint 的原因,其后果将严重影响代币的供应总量,进而干扰代币所对应生态系统。

防御策略:

对于 ERC20/TRC20 等代币合约,Ethereum/Tron 平台上都有一些开源且经过实践验证的公共代码库,例如 OpenZeppelin 提供的 openzeppelin-solidity/SafeMath.sol at master · OpenZeppelin/openzeppelin-solidityopenzeppelin-solidity/ERC20.sol at master · OpenZeppelin/openzeppelin-solidity 库,项目方开发人员在不影响业务逻辑的前提下应当尽量复用这部分代码,避免重复造轮子。


TransferMint 漏洞详解:超20个波场合约存无限增发代币风险

PeckShield(派盾科技)是面向全球顶尖的区块链数据与安全服务提供商。商业与媒体合作(包括智能合约审计需求), 请通过 ********、Twitter 或邮件 ([email protected])与我们联系。