SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

区块链技术巴比特2018-04-25 20:57:26  阅读 -评论 0  阅读原文

1 整数安全回顾

1.1 整数安全简介

​ 在传统的桌面windows攻防对抗领域,伴随着微软和合作伙伴对软件开发流程推行SDL规范,同时对安全投入的逐步加大,单一的封包超长和文件特定字段内容超长导致的溢出漏洞在一些大型软件里几乎绝迹。剩余漏洞除了浏览器中的UAF(有隔离堆和延迟释放对关键类进行利用缓解),弱类型语言存在的类型混淆,还零星剩下了一些整数类的漏洞。整数类漏洞,最近的如去年的nginx cve-2017-7529。

区块链方向,比较早的整数溢出类漏洞可追溯到2010年的比特币大整数溢出,CVE-2010-5139 ,黑客通过整数溢出构造了大概92233720368.54277039 个比特币,最近的SMT/BEC的整数安全场景与之前比特币的场景类似。

​ 传统安全领域中,整数安全与数据模型和整数运算支持的运算符相关,其中数据模型又跟处理器架构体系和操作系统平台相关。如下图。

SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图1

C中容易引发整数安全问题的运算符简要罗列如下。

SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图2

Solidity合约中的整数安全场景与之类似。

 1.2 Solidity中的整数安全场景

SMT和BEC都是以太坊代币生态下的一个普通的ERC-20代币。转账流通都是通过以太坊的solidity合约进行实现。

区块链1.0的比特币也有脚本语言,但是为了安全阉割掉了循环和递归等图灵完备性语言才有的功能。以太坊Solidity设计之初就被定位为图灵完备性语言。Solidity的图灵完备性也为后续的合约漏洞陆续埋下了伏笔,如The Dao漏洞事件直接导致以太坊硬分叉成了eth和旧链etc。

Solidity语言暂不支持类似于C中的float double等浮点型数据类型。支持int/uint变长的有符号或无符号整型。变量支持的步长以8递增,支持从uint8到uint256,以及int8到int256。需要注意的是,uint和int默认代表的是uint256和int256。uint8的数值范围与C中的uchar相同,即取值范围是0到2^8-1,uint256支持的取值范围是0到2^256-1,余下数据类型以此类推。

Solidity语言中对于运算符的支持如下。

比较:<=,<,==,!=,>=,>,返回值为bool类型。 位运算符:&,|,(^异或),(~非)。 数学运算:+,-,一元运算+,*,/,(%求余),(**平方)。

Solidity合约代码的逻辑都相对简单,运算符的使用中加法 减法和乘法居多。

以太坊提供有一个Solidity语言的在线编译测试工具。http://remix.ethereum.org/#optimize=false&version=soljson-v0.4.23+commit.124ca40d.js 我们以加法和减法运算作为举例,简单说明下整数溢出在Solidity语言中的常规情况。

编写如下solidity测试代码。

pragma solidity ^0.4.0; contract C { // (2**256 - 1) + 1 = 0 function overflow() returns (uint256 _overflow) {     uint256 max = 2**256 - 1;     return max + 1;     } ​ // 0 - 1 = 2**256 - 1 function underflow() returns (uint256 _underflow) {     uint256 min = 0;     return min - 1;     } }

在线测试工具中编译运行结果如下。

SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图3

SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图4

可以看到uint256当取最大整数值,上溢之后直接回绕返回值为0,uint256当取0下溢之后直接回绕,返回值为2^256-1。这是solidity中整数溢出场景的常规情况。

  1.3 Solidity中的整数溢出缓解和SafeMath库

为了减少solidity合约开发中产生的安全问题,以太坊的官方开发博客陆续发布了一些与solidity开发安全相关的博文。在2017年8月6日单独发过一篇使用SafeMath库进行整数安全操作的文章<< SafeMath to protect from overflows >>。详见链接

​ https://ethereumdev.io/safemath-protect-overflows/

/**  * @title SafeMath  * @dev Math operations with safety checks that throw on error  */ library SafeMath {   function mul(uint256 a, uint256 b) internal constant returns (uint256) {     uint256 c = a * b;     assert(a == 0 || c / a == b);     return c;   }   function div(uint256 a, uint256 b) internal constant returns (uint256) {     // assert(b > 0); // Solidity automatically throws when dividing by 0     uint256 c = a / b;     // assert(a == b * c + a % b); // There is no case in which this doesn't hold     return c;   }   function sub(uint256 a, uint256 b) internal constant returns (uint256) {     assert(b <= a);     return a - b;   }   function add(uint256 a, uint256 b) internal constant returns (uint256) {     uint256 c = a + b;     assert(c >= a);     return c;   } }

可以看到相关的可能产生溢出的操作都单独封装成函数,加入assert断言做判断避免溢出。调用SafeMath库的方法如下。 SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图5

2. SMT合约中的整数安全问题简析

与大型软件或者操作系统动辄十万行甚至千万行代码不同,智能合约的代码行数通常不多,功能也不是很复杂。一起来看下SMT合约的相关代码。

SMT的合约地址是https://etherscan.io/address/0x55f93985431fc9304077687a35a1ba103dc1e081#code

问题存在于transferProxy()函数 代码如下

SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图6

在进行加法操作的时候没有采用Safemath库进行约束。_feeSmt参数和_value参数均可以被外界进行控制, _feeSmt和value均是uint256无符号整数,相加后最高位舍掉,结果为0。

SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图7

直接溢出绕过代码检查导致可以构造巨大数量的smt代币并进行转账。

SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图8

攻击者的恶意转账记录可以从如下链接进行看到。

https://etherscan.io/tx/0x1abab4c8db9a30e703114528e31dee129a3a758f7f8abc3b6494aad3d304e43f

SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图9

3. BEC合约中的整数安全问题简析

BEC的合约地址是0xC5d105E63711398aF9bbff092d4B6769C82F793D,合约代码可以访问etherscan的如下网址进行查看https://etherscan.io/address/0xc5d105e63711398af9bbff092d4b6769c82f793d#code。代码一共是299行。

问题函数如下图。

SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图10

可以看到batchTransfer函数中,语句balances[msg.sender] = balances[msg.sender].sub(amount)和balances[_receivers[i]] = balances[_receivers[i]].add(_value)中,调用Safemath库中的安全函数来完成加减操作,但是在第三行代码,  uint256 amount = uint256(cnt) * _value却直接使用乘法运算符。

其中变量cnt为转账的地址数量,可以通过外界的用户输入_receivers进行控制,_value为单地址转账数额,也可以直接进行控制。乘法运算溢出,产生了非预期amount数值,并且外界可以通过调整_receivers和_value的数值进行操控。紧接着下面有一句对amount进行条件检查的代码 require(_value > 0 && balances[msg.sender] >= amount);其中balances[msg.sender]代表当前用户的余额。amount代表要转的总币数。代码意思为确保当前用户拥有的代币余额大于等于转账的总币数才进行后续转账操作。因为通过调大单地址转账数额_value的数值,amount溢出后可以为一个很小的数字或者0,很容易绕过balances[msg.sender] >= amount的检查代码。从而产生巨大_value数额的恶意转账。

攻击者的恶意转账记录,可以从如下链接看到https://etherscan.io/tx/0xad89ff16fd1ebe3a0a7cf4ed282302c06626c1af33221ebe0d3a470aba4a660f。

SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图11

可以从代码totalSupply进行看到,bec代币总量共计才7 000 000 000枚。

SMT/BEC合约整数溢出解析——Solidity合约中的整数安全问题

图12

但是攻击者通过溢出amount绕过后续require中的判定条件分别向两个地址恶意转账了 57,896,044,618,658,100,000,000,000,000,000,000,000,000,000,000,000,000,000,000.792003956564819968枚bec代币。

4. 合约整数漏洞事件总结

单纯从技术上来说,smt和bec的本次合约的漏洞成因和利用都不复杂,均是通过构造恶意的整数溢出绕过条件检查。相信以太坊生态下的其他数千种代币的合约也不同程度的存在类似的整数漏洞安全隐患,由于solidity合约是直接跟钱打交道,合约的安全开发和审计值得ico项目方和solidity开发人员投入更多时间和精力,确保合约的安全性。

参考链接:

https://ethereumdev.io/safemath-protect-overflows/

https://zhuanlan.zhihu.com/p/35989258?utm_medium=social&utm_member=ZjZlYmQ1MGZkMjZjZmJkNTE4MGFmMmExZjA5NTM0NmE%3D&utm_source=wechat_session&wechatShare=1&from=timeline&isappinstalled=0

声明:链世界登载此文仅出于分享区块链知识,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不构成投资建议。投资者据此操作,风险自担。此文如侵犯到您的合法权益,请联系我们100@7234.cn

    参与讨论 (0 人参与讨论)

    相关推荐

    区块链投资趋势报告:巨头入场布局行业趋于成熟

    区块链投资趋势报告:巨头入场布局行业趋于成熟

    来自:https://mp.weixin.qq.com/s?__biz=MzI4NzIxOTY1NA==&amp;mid=2650632639&amp;idx=1&amp;sn=e6d1c29731d992a80410aaee82ec3ea6&amp;chksm=f3d8db16c4af520097e4a64a71b1d4743ac326b9f027

    重新发明货币

    重新发明货币

    一、货币的演化过程 先简单回顾一下人类货币的演化过程,大概有以下阶段: a. 1.0版本:自然货币(贝壳、牲口、金银……) 这个阶段,货币基于一般等价物的稀有性或者实用性,货币不可能出现人为操纵的超发。 b. 2.0版本:早期纸币、银票到本位纸币 当贸易量越来越大,实物货币太不方便了,而且大家发现其实并不在意货币本身有什么价值,在意的只是这么多的货币能不能交换到足够的物品,于是纸币这种信用货

    从比特币交易看欧洲央行虚拟货币分类

    从比特币交易看欧洲央行虚拟货币分类

      互联网对传统社会的颠覆从未停止,在其完成对信息流、商流、物流、资金流的初步改造之后,或将以虚拟货币的形式打破现有货币体系   4月18日,在中国极客张沈鹏创办的比特币交易平台(42BTC.com)上,比特币对人民币的平均交易价为576元。当天,该平台完成了100个比特币的交易量。仅仅过去一周,4月25日上午,比特币对人民币的平均交易价已达到906元。据42BTC网站统计:在过去的32个月

    欧洲央行-比特币报告

    3.1 比特币 3.1.1 基本特征          比特币可能是最成功的,也可能是最有争议的虚拟货币方案,由日本程序员中本聪(译者注:事实上,中本聪是不是日本人,甚至是不是单个人无从考证)在2009年设计并实现。该计划基于一个类似于BitTorrent的P2P网络。BitTorrent是互联网上著名的共享文件协议,应用在电影,游戏和音乐领域。比特币在全球层面上运作,可用于各类货币交易(虚

    彻底玩转比特币地址和私匙

    彻底玩转比特币地址和私匙

    比特币地址和私匙是所有比特币初学者面对的一大难题,再加上那一串超长的字符串,让人更是摸不到头脑。 现在编者以问答的形式,带你一步步的揭开比特币地址和私匙的面纱。 还不知道什么是比特币地址和私匙的同学请点这里 问题一、比特币钱包由什么组成? 答 我们知道,比特币地址和私匙组成了比特币钱包,而私匙则决定了比特币地址上比特币的归属。 地址和私匙 问题二、如果只记得私匙我们还能还原比特币地址么? 答

    用GO语言实现比特币算法

    用GO语言实现比特币算法

    本节的这个例子展示一点点高精度数学包math/big、一点点散列包hash、一点点加密包crypto,还有一点点测试包testing的知识。这里不介绍bitcoin协议和算法——尽管它们很有趣,而是试图指出,Go对多种操作系统的支持,是实现这种跨平台应用的理想语言。 位钱(bitcoin)是一种使用加密手段制作的分布式电子货币。它最初于1998年由Wei Dai提出,并由中本聪(Satoshi

    详解比特币的找零机制

    详解比特币的找零机制

    比特币的找零机制一直让人有些迷惑,明明只向一个地址发送了比特币为什么 blockchain 上面的显示的有时是1个地址对多个地址,有时是多个地址对1个地址,有时又显示多个地址对多个地址? 为什么比特币资深用户要提醒大家当比特币钱包交易100次以上时再次交易后要重新备份钱包,恢复以前的钱包备份有可能会遭遇损失? 是的,这一切都是因为比特币的找零(Change)机制。本文参考 Bitcoin的维

    玩转比特币客户端之一:C盘转移和加速下载

    玩转比特币客户端之一:C盘转移和加速下载

    C盘空间不足?交易数据下载速度太慢?别着急,乐享比特币教你轻松玩转比特币官方客户端。 所有新人开始接触比特币时做的第一件事情大多数是安装比特币的官方客户端。 安全起见大家最好直接访问官方发布渠道sourceforge的地址进行下载:http://sourceforge.net/projects/bitcoin/files/Bitcoin/ 该网页列出了各版本的官方比特币客户端,目前

    麦妖榜
    更新日期 2019-01-17
    排名用户贡献值
    1等待的宿命23695
    2BitettFan23632
    3六叶树20309
    4天下无双16192
    5lizhen00214782
    6区块大康14502
    7让时间淡忘14188
    8冷风大q11188
    9momo11174
    10linjm122710573
    返回顶部 ↑