收藏(0)

04 月 11 日凌晨 00:17,PeckShield 态势感知平台监测到 TCX1Cay… 开头的黑客,创建了名为 BTTx, token id 为 1002278 的 TRC10 token,并于凌晨 00:25 至 01:00 之间向多个地址转入 4,000 万个 BTTx 代币,这多个地址对 TXHFhq… 开头的 BTTBank 理财类合约实施攻击。

BTTBank 项目介绍

BTTBank 又名 TronBank BTT, 是属于 TronBank 旗下的一款专属于 BitTorrent (BTT) – The token that will enable blockchain mass adoption BTT token 的投资产品,根据官网 TronBank 介绍:

TronBank BTT 的智能合约将为您产生每天 3.6 – 6.6%的投资收益(取决于你购买的产品计划),自动发放到你的收益余额中。举例,购买 4.6% 收益计划,21 天你即可获得超过 100% 收益。收益每秒都会计算,你甚至每秒都可以提取收益或重新投资。当您重新投资收益时,投资金额会增加,可以更快的获得更多收益。

其产品界面如下(由于当前 BTTBank 在维护中,主站无法打开,援引 TronBank 明星产品 TRX 的投资图片,详见 TronBank):

其理财过程大致如下:

1、用户根据收益率和投资期限购买相应的理财产品;

2、投资期限到期之后,用户提现理财产品到自己的钱包。

使用上,和当前的各类 P2P 理财产品类似,用户的使用门槛仅在于一个 TRON 钱包,但从产品收益率来看,这个资产回报率还是相当可观的。

攻击回溯

攻击事件简述

去年年底,波场孙宇晨发起 12 号提议,即符合波场 TRC10 规范的 Native token 的名字将不再唯一,涉及到 TRC10 token 的转账等操作将使用 ID 来代替。这使得波场创建 token 的流程变得简单易上手,然而却带来一个潜在的威胁,一旦合约疏于检查 token id 的匹配性,就会存在假币攻击的可能。简而言之,本次 BTTBank 遭受攻击正是因为缺乏 token id 的一致性验证造成的。

背景知识

TRON 中的 token 分为几种规范:

  • TRX
  • TRC20
  • TRC10

其中,TRX 为 TRON 的平台币,类似于 Ethereum 中的 ETH。

而 TRC20 是与 Ethereum ERC20 兼容的 token,实质是一种可编程的智能合约,由用户通过智能合约创建 token 之后,其 token 的转账、发送等操作均在智能合约内部完成,对于一般的小白用户来说,ERC20/TRC20 使用过于复杂,不便于上手使用。

故此,TRON 中引入了 TRC10 token, 这是一种可以由用户直接操控的 token,每一个自然用户支付 1024 TRX 便可创建一个 TRC10 token,同时一个用户只能创建一个 TRC10 token。每一个 TRC10 token 在创建之后,由系统分配一个唯一 ID (即 token id),这是一个从 1,000,001 开始往后自增的整数,一个 tokenId 标识一个唯一的 token,当前 TRON 平台上共有 1850+(2019-04-12)个 TRC10。

为了提高 TRC10 的流动性和使用价值,TRON 平台在 Odyssey 3.2 版本之后,使能了在智能合约内部转账 TRC10 token 的功能,参考 TRC10 Transfer in Smart Contracts, 其示例代码如下所示:

上述代码简单解释如下:

1、transferTokenTest() 接口内部用于转账 TRC10 token,接口调用方可以通过 address.transferToken(uint256 tokenValue, trcToken tokenId) 往 address 转账数量为 tokenValue 的 token id 为 token id 的 TRC10 token;

2、msgTokenValueAndTokenIdTest() 接口表明,调用者可以直接在发送的 message 中加入 token id 和 tokenvalue 字段,这也说明了 TRC10 是 TRON 平台上的一等公民,属于内置类型,与 TRC20 通过函数参数的形式来表征 token 价值是完全不同的;

3、getTokenBalanceTest() 通过 token id 获取账号的余额。

由此可知,TRC10 token 可以在智能合约内部通过 token id 完成转账,TRC10 token 作为价值承载者,在智能合约内部即反映在 token id 的差异上。

因此,合约开发者在处理 TRC10 转账相关逻辑时,需要特别注意 token Id 的有效性和真实性。

攻击事件

PeckShield 安全人员在分析 BTTBank 合约时,发现其合约源码实现中存在致命漏洞,可导致项目方资金受损。

下图为黑客攻击的原过程:

1、黑客先行创建一个名为 BTTx 的 TRC10 token;

2、黑客往一批自己控制的账号中转入 4,000 万个 BTTx token;

3、通过控制的账号往 BTTBank 合约发起数次攻击;

4、最后顺序将 BTT 提取到控制的账号中。

下文从 BTTBank 投资及赎回的过程还原本次 BTT 假币攻击的全过程。

投资

投资的核心代码如下:

public 接口的 invest( ) 提取 msg.tokenvalue ,并调用 private 的 invest( ) 函数完成投资的过程,invest( ) 内部计算并保存用户这一次的投资数量、时间等信息到合约的内部资产账单上。值得注意的是,这里 invest( ) 只提取了 msg.tokenvalue,这里并没有提取 msg.tokenid,也没有验证 msg.tokenid 是否属于 BTT Token 的 token id(为 1002000)。

前面我们提到 BTTBank 是一款投资理财类 DApp,用户存入 BTT token,资产到期之后,再赎回投资的 BTT 和对应的利息,在这里并没有检查是否是真正的 BTT,也就是不论你投资的阿猫阿狗币,都被认为是 BTT token。

提现

提现的核心代码如下:

赎回的过程比较简单,先从合约的内部投资账单上计算用户已经到期的投资金额,并将这一部分投资金额转回给用户,注意:msg.sender.transferToken(withdrawalAmount, BTT_ID) 中是固定的 BTT_ID 即 1002000.

至此,用户投入 BTT,收获 BTT;而黑客投入 BTTx, 收获 BTT,一个完美的『狸猫换太子』过程。

防御策略

PeckShield 安全人员在此提醒广大开发者,虽然 TRC10/TRC20 都是 token, 但两者在 TRON 平台上有着本质的差异性,若要在智能合约内部转账 TRC10,一定要检查所转移的 TRC10 对应的 token id 是否为预期值。针对上例,可将投资代码增强如下:

另外,PeckShield 安全人员根据上述的代码样式分析 TRON 平台上其它类 BTTBank 合约时,也发现了相似的问题。在此,PeckShield 安全人员提醒在进行智能合约开发的时候,虽然复用现有代码可能会带来开发功能上面的便利,但也须注意可能带来的安全风险。

仅一条评论

请输入你的评论!
请在这里输入您的名字