天才程序员: "那些年我偷懒没敲的EOS代码, 让我失去了一切, 如果..."

2019-04-28 17:38:16 浏览数 (1)

作者 | 红石

责编 | 乔治

出品 | 区块链大本营(blockchain_camp)

#今天是一篇技术文。

3月15日,mercatox 遭受(hard_fail)攻击,黑客获利数千 EOS,约合数万人民币。

3月11日,EOS DApp nkpaymentcap 被攻击,黑客成功获利 5 万 EOS,约合人民币100多万元。经分析发现,攻击者采用假转账通知攻击获取大量合约代币,又将代币通过 DApp 合约兑换成真 EOS 进行套现。

3月10日,EOS 竞猜类游戏 Vegas Town 被连续(hard_fail)攻击,黑客获利数千枚 EOS 。

3月9日,EOS 竞猜类游戏 Gamble EOS 遭受假转账攻击,黑客成功获利数千 EOS……

仅仅三月份,利用交易验证漏洞进行的攻击就已经有这么多起,损失达上千万人民币。

那么,什么是交易验证漏洞?为何 EOS 让你频频“丢钱”?BM告诉你,是你的代码“太笨”。

先说说交易验证,你不了解交易验证,但黑客了解。

因为在支付领域,这很重要。在区块链领域,无论做 DApp,还是接入数字货币支付,交易验证都是重要部分。

交易验证,说起来也简单:就是如何确认一笔金额已经到账。

说起来也不简单,因为会有无数黑客试图让并未成功的交易通过验证,从而空手套白狼。

比如最近针对 EOS 交易的 hard_fail 状态攻击,就是这样一种黑客攻击。

hard_fail 状态攻击

在 EOS 区块链上,每笔交易(transaction)都有一个状态(status)参数,只有当这个参数为 executed(已执行),才说明交易成功。但是因为一般来说,失败的交易都不会提交到链上,所以,一些不谨慎的交易所、DApp 甚至没有验证这个参数。

这才有了最近的 hard_fail 状态攻击。其实这个攻击手法的背后原理远比它的名字简单,就是黑客发起了注定失败的、但是又能上链的交易,专门攻击那些只要交易上链就视作交易成功的平台。

不试不知道,一试吓一跳,真的有很多平台没验证这个参数……

那么,EOS 交易验证到底需要验证些啥?

EOS 交易验证涉及的参数

EOS 交易验证,需验证:

1、交易 excuted,验证 transaction status 参数为 executed,验证这个参数可以有效避免 hard_fail 状态攻击;

说简单点,这一步是验证交易是否正常执行。

2、不可逆,即交易所在区块号低于当前最新不可逆块号,需要获得 transaction 所在区块的区块号,以及主网最新不可逆块的区块号(不可逆区块高度),判断:

block_num < last_irreversible_block_num;

说简单点,这一步是验证交易是否已经同步。

区块链是分布式账本,交易提交上去后,需要大多数节点记录了这笔交易,才能认为交易已上链并不可篡改。不然的话,比如如果只有一个节点有这笔交易,则只要这个节点的交易信息一改,这笔交易就变了。

3、合约账户和货币符号;

合约账户就是货币的智能合约账户。EOS 区块链转账都是基于智能合约的,比如 EOS 币的智能合约账户就是 eosio.token,每一次进行 EOS 币转账,都会调用这个合约。

假币攻击就是因为交易所没验证合约账户。

4、交易(action)类型为 transfer;

EOS 区块链上的交互都是以 transaction 进行,无一例外。所以,不是每一笔 transaction 都包含转账。EOS 一笔 transaction 可以有多个 action,只有类型为 transfer(转账)的 action,才是转账,才是需要做交易验证的。

5、From 和 to,即转入转出的账户需要再次确认。

交易(Transaction)同时满足这些条件,才能判断为交易成功,并执行下一步程序。而且,如果是通过公共 API 或 API 服务商提供的数据进行交易验证,需要使用不同服务提供商的 API 至少进行二次确认,以防止 API 信息出错导致问题。

那么问题又来了,如何通过公共 API 进行交易验证呢?

通过 EOSPark API 获取交易、进行交易验证

让我们以 EOSPark 的 API 服务做个基本示例。

EOSPark 本身是一个主流 EOS 区块浏览器,但他们也面向开发者提供 API、代码一致性校验、合约安全(SEC)、合约语义化等服务。

1、EOSPark API 官网: https://eospark.com/openapi 2、EOSPark API 官方文档: https://developer.eospark.com/api-doc/zh/https/

EOSPark API 服务思维导图:

EOSPark API 有四种查询 EOS 交易的方式。

根据账户查询:

HTTPS API get_account_related_trx_info Websocket API subscribe_account

根据 txID 查询:

HTTPS API get_transaction_detail_info HTTPS API get_transaction_action_info

以 HTTPS API get_account_related_trx_info 为例,这个接口能查询对应账户的进出交易,无论是收到的转账还是发起的转账,都可以一起查到:

get_account_related_trx_info 的基本查询语句如下:

https://api.eospark.com/api?module=account&action=get_account_related_trx_info&apikey= {这里放你的 API KEY}&account={这里放 EOS 账户名}&page=1&size=10

语句填好参数后可以直接在普通浏览器中打开查询信息,不过当然,我们更习惯用 IDE:

Node.js 代码示例:

返回 JSON 示例:

可以看到在 get_account_related_trx_info 返回的信息中,本来就包括交易所在区块号(block_num)和不可逆区块高度(last_irreversible_block_num)。

同时 status、code(合约账户)、symbol、From(这里是 sender)和 to(这里是 receiver)这些参数也一应俱全。(交易类型因为这个接口本身就是返回转账交易,所以这里可以不作验证。)

也就是说,使用这个接口,查询一次就可以直接验证获取到的交易。

那么问题又来了,也就是说,有些时候查询的信息不能直接进行交易验证?

很不幸,是滴。

获取不可逆区块高度和交易状态的补充方法

有些接口返回的交易信息不包含交易验证所需所有参数,需要再另外获取。最常见的就是不可逆区块高度的缺失,还有一些直接查询 actions 的接口有交易状态参数缺失。

不过处理起来都很简单。

同样以 EOSPark API 服务为例:

获取不可逆区块高度,使用 RPC 接口 get_info 就好,这是一个获取 EOS 主网基本信息的接口:

Node.js 代码示例:

返回 JSON 示例:

获取状态参数,可以使用 HTTPS 接口 get_transaction_detail_info,这是一个根据 txID 查询交易(transaction)详情的接口:

查询语句:

https://api.eospark.com/api?module=transaction&action=get_transaction_detail_info&apikey= {这里放你的API KEY}&trx_id={这里放查询的交易ID}

返回 JSON 示例:

至此,我们就简单说完了 EOS 区块链交易验证的一个基本思路。当然,具体情况具体分析,具体开发时验证的方式不一定按这样来。不过条条大路通罗马,思路是一样的,验证的参数也基本都是这些。

0 人点赞