智能合约平台共识机制,本质上是将所有的交易【Tx_1 Tx_2 ……. Tx_n】按顺序作用到初始State_0上,使全网始终保持相同的状态。在状态机复制过程中,我们要求State_n × Tx_èState_是决定性的。State_n × Tx_èState_实质上就是智能合约虚拟机对Tx_的执行过程,如果智能合约虚拟机中存在设计或者实现漏洞,导致虚拟机不一致性执行(对相同的输入State_n 和Tx_,输出State_不一致)。则攻击者可以利用该问题在网络中产生分叉和并进行双花攻击。下面我们介绍多个EOS和NEO上我们发现的虚拟机不一致执行漏洞和其产生原因。
4.1 EOS虚拟机内存破坏RCE漏洞:
此前,我们公开了文章《EOS Node Remote Code Execution Vulnerability --- EOS WASM Contract Function Table Array Out of Bound》(http://blogs.360.cn/post/eos-node-remote-code-execution-vulnerability.html)。在该文中,我们发现了一个EOS WASM虚拟机的一个内存越界写漏洞,针对该漏洞我们编写的利用程序可以成功利用该漏洞使EOS虚拟机执行任意指令,从而完全控制EOS所有出块和验证节点。
究其本质而言,是在State_n × Tx_{n+1} → State_{n+1}过程中。攻击者能让EOS虚拟机完全脱离原本执行路径,执行任意指令,自然可以完成双花攻击。其攻击流程如下:
步骤1:攻击者构造能够实现RCE的恶意智能合约,并将该合约发布到EOS网络中。
步骤2:EOS超级节点解析到该合约后,触发漏洞,执行攻击者自定义的任意指令。
步骤3:攻击者实现双花攻击。
该漏洞的危害非常严重,且是第一次智能合约平台受到远程代码执行攻击事件。读者可以阅读该文章了解相关细节,在此不再赘述。
4.2 EOS虚拟机内存未初始化造成双花攻击:
我们在编写《EOS Node Remote Code Execution Vulnerability --- EOS WASM Contract Function Table Array Out of Bound》的利用程序的过程中,还利用了EOS中当时的一个未公开的内存未初始化漏洞。在内存破坏攻击中,内存未初始化漏洞通常能够造成信息泄露、类型混淆等进一步问题,从而辅助我们绕过如ASLR之类的现代二进制程序的缓解措施,进一步实现攻击。然而在智能合约虚拟机中,内存未初始化漏洞有更直接的利用方式,可以直接造成双花攻击。以下为我们在EOS RCE中利用的一个内存未初始化漏洞的细节,其可以被用来直接实现EOS智能合约代币资产双花攻击。
当WASM虚拟机通过grow_memory伪代码来申请内存新的内存。在EOS WASM grow_memory最初的实现中,未对申请到的内存进行清零操作。该块内存的空间实际上是随机的(依赖于合约执行机器的内存状态)。则攻击者可以构造恶意合约,实现对EOS上任意合约资产的双花攻击。其攻击流程如下:
步骤1: 攻击者构造恶意智能合约。合约中通过grow_memory获得一块新的内存地址。
步骤2:合约中读取该地址中的某个bit内容(此时该bit可能为0,也可能为1,依赖于合约执行机器的状态)。
步骤3:合约判断该bit的内容,如果为1则发送代币给A用户,如果为0则发送代币给B用户,从而实现双花攻击。
4.3 EOS虚拟机内存越界读造成双花攻击:
在传统的内存破坏中,内存越界读漏洞主要将会导致信息泄露,从而辅助我们绕过如ASLR之类的现代二进制程序的缓解措施,进一步与其他漏洞一起实现攻击。然而在智能合约虚拟机中,内存越界读漏洞有更直接的利用方式,可以直接造成双花攻击。下面为一个我们发现的EOS内存越界读漏洞,我们可以利用该漏洞实现双花攻击。
当EOS WASM将一个offset转换内WASM内存地址时,其边界检查过程如下: