一、前言

最近审计了一波以太坊CVE,本章中提及的漏洞包含了众多问题,不仅包括代码上的漏洞,还包括由于函数设计问题而导致的金融学上的漏洞。在分析漏洞之余,我也对本文出现的问题进行进一步思考,并将感想分享给读者。

该漏洞仅为这一类漏洞的代表,与其相关的类似合约还有许多,这里仅使用最有代表性一个来进行分析演示。

首先需要简单的介绍一下相关背景。本文安全隐患是以PolyAI 、Substratum为代表的一类项目。Substratum项目主要是打造基于区块链的网络, 简而言之,就是重构现在的互联网服务,包括 DNS, 网络空间存储等,其中解决“国际性网络封锁” ,完全为中国定制,可以解决国内需要通过VPN服务才可以翻墙访问国外网站的问题。从官网看来,开发者应该很了解中国国情,网站和白皮书的中文都下了很多功夫,做得很地道,证明开发团队非常重视中国市场。

POLY AI 聚焦于基于深度学习的人工智能,谷歌、苹果、Facebook最近在这个领域贡献了巨大的成果,POLY AI 使用区块链技术来解决深度学习训练过程中的计算消耗和数据源问题,而且区块链也比所有传统技术更能够提供安全保障。

这些币种的实用性很强,均为某个领域提供支持。

二、问题所在

该类型的应用包括三类问题。首先为可超额铸币。

为了方便管理员对应用进行管理,设计者在设计此类应用的时候添加了发币接口。此类发币接口的使用者为owner并且能够没有限制的增加自身发币数量。

function mintToken(address target, uint256 mintedAmount) onlyOwner {
        balanceOf[target] += mintedAmount;
        totalSupply += mintedAmount;
        Transfer(0, this, mintedAmount);
        Transfer(this, target, mintedAmount);
    }

该函数拥有两个参数,包括目标地址与发币数量。当owner调用此函数的时候,其可传入待处理钱包地址并能够任意为钱包账户增加余额。这种方法看似增加了合约的灵活性,能够更自主的去修改合约中的各种变量,但是我们都知道,对于货币来说,这种无代价的超额增发会导致各种问题。虽然此类函数是owner所用, 如果恶意owner存在,那么他便能够任意增加账户货币数量,当其数量增多时,货币的市场价值便会受到影响。

其次,该类型合约均存在严重的漏洞,即乘法溢出。

下面我将举例两个例子。

首先我们来看Substratum合约中的函数。

在合约的关键转账函数中,设计者对溢出做出了判断。

function transfer(address _to, uint256 _value) {
        if (balanceOf[msg.sender] < _value) throw;           // Check if the sender has enough
        if (balanceOf[_to] + _value < balanceOf[_to]) throw; // Check for overflows
        if (frozenAccount[msg.sender]) throw;                // Check if frozen
        balanceOf[msg.sender] -= _value;                     // Subtract from the sender
        balanceOf[_to] += _value;                            // Add the same to the recipient
        Transfer(msg.sender, _to, _value);                   // Notify anyone listening that this transfer took place
    }

即:if (balanceOf[_to] + _value < balanceOf[_to]) throw;当转账金额溢出时执行throw操作。

然而在后面的卖出函数中却没有进行溢出判断。

function mintToken(address target, uint256 mintedAmount) onlyOwner {
        balanceOf[target] += mintedAmount;
        totalSupply += mintedAmount;
        Transfer(0, this, mintedAmount);
        Transfer(this, target, mintedAmount);
    }

    function freezeAccount(address target, bool freeze) onlyOwner {
        frozenAccount[target] = freeze;
        FrozenFunds(target, freeze);
    }
点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖