讲溢出攻击之前,先给大家讲个故事:2014年的时候,美国的宾夕法尼亚州的某个小镇上发生了一个乌龙事件,征兵系统对一万多名1893年到1897出生的男子发去信函,要求他们注册参军,否则面临罚款和监禁。收到信函的人啼笑皆非,因为这些信函指明的人都是大部分都是他们已故的祖父外祖父。导致这个事件的原因就是“千年虫”。

严格的说“千年虫”属于程序的一个BUG。因为在上个世纪,计算机的存储空间很小,使用人员为了最大化利用计算机的存储空间,规定了在计算机中存储年份的时候使用两位数字来表示,如“1998”年,那么计算机中的存储值则为“98”。当千禧年来临的时候,这个值就会变成“00”,这个时候计算机就不知道这个“00”代表的是1900年还是2000年,所以才会出现刚才文章开始的乌龙事件,这也是我们本文要讲述的”溢出“的概念。

事件介绍

2018年4月23日,一款名为BEC的代币被黑客攻击。黑客利用合约内的漏洞,短时间向外部的账户转入了天价的合约代币, 导致该代币价格迅速缩水几乎归零。攻击手法被披露的24小时内,就有三十多个合约被类似手法攻击。

漏洞原因

在solidity语言中,对int类型的数据变量规定了长度,如uint8代表的是无符号的8位整数,即0到255。假如有下面一个简单的合约:

pragma solidity ^0.4.25;
contract test{
  function add(uint8 _a) public pure returns(uint8){
      return _a+1;
  }
   
}

可以发现传入的参数是一个uint8类型变量,它的范围在0-255,如果输入的值是255,那么返回的结果会是什么呢?有兴趣的读者可以到remix中试一下,返回值会是0,如果输入256,返回结果会是1。造成这样的原因主要跟数据在计算机中的存储有关,计算机只给uint8的类型变量分配了长度为8的空间,最大值为255,如果超过这个值会产生进位之后被截断,导致存储的8位全部都是0,这就造成了整数溢出。

下面看一下BEC合约中的一个函数:


function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) {
  uint cnt = _receivers.length;
  uint256 amount = uint256(cnt) * _value;
  require(cnt > 0 && cnt <= 20);
  require(_value > 0 && balances[msg.sender] >= amount);   balances[msg.sender] = balances[msg.sender].sub(amount);
  for (uint i = 0; i < cnt; i++) {
      balances[_receivers[i]] = balances[_receivers[i]].add(_value);
      Transfer(msg.sender, _receivers[i], _value);
  }
  return true;
}

这个函数的目的是实现一个批量转账的功能,receivers是接受者的数组,value是转账金额。重点关注

 uint256 amount = uint256(cnt) * _value;

这里定义了一个uint256类型的变量amount来接收转账的总金额,后续会通过这个金额的值和用户所发送的金额比较来判断用户是否能够发送这么多的代币。那么重点来了,如果uint256(cnt) * _value的值超过uint256,不就产生了溢出了吗?攻击者通过传递两个账户,__value为2的255次方(实际上是转换成了16进制),2*2^255=2^256完成了溢出,amount的值为0。这个逻辑下的amount能够通过后面的所有校验,最后发送给两个账户的值确是2的255次方的代币。

BEC车祸现场连接:https://etherscan.io/tx/0xad89ff16fd1ebe3a0a7cf4ed282302c06626c1af33221ebe0d3a470aba4a660f

防范

跟攻击手段一样,针对BEC的溢出攻击的防范也非常简单。我们可以利用safeMath库来避免这种情况。把 uint256(cnt) * _value改成 uint256(cnt) .mul(value)即可。相信稍微有点solidity编程经验的读者都能知道怎么做。BEC遭受的整数溢出的攻击原理非常简单,但是在攻击手段被披露的24小时内就有30多个合约被攻击,这也不得不引起我们的重视和思考:合约本身并不具备安全的属性,却动辄承载上千万价值的代币,我们过往对于合约的安全评估是否过于乐观?

智能合约安全事故回顾(2)-BEC溢出攻击的更多相关文章

  1. 【原创】智能合约安全事故回顾分析(1):The Dao事件

    首先需要说明的一点是,这个世界上没有绝对安全的技术.在区块链发展的十年里,各种基于区块链的数字货币引发的安全事故层出不穷,这些安全威胁主要来源有三个方面: 自身安全机制的问题,类似智能合约. 生态安全 ...

  2. 智能合约安全事故回顾(3)-DOS漏洞导致的KotET事件

    现实世界中的网络都是有带宽限制的,想象一下,一个访问量稳定的网站,突然有人利用某种方式爆发式的将网站的访问量提升,这个时候系统会作何反应?如果系统没有合理的防DOS攻击的方式,这种时候往往会造成服务器 ...

  3. 智能合约bug以及修改方案

    截取两篇文章:第一遍文章说的是智能合约能不能修改的问题: ETC转到ETH地址以及转币进ETH智能合约账户能不能转出来? 第0章 引言 如果ETC充值到了ETH地址上,能找回来吗?答案是不一定. ET ...

  4. 智能合约语言 Solidity 教程系列8 - Solidity API

    这是Solidity教程系列文章第8篇介绍Solidity API,它们主要表现为内置的特殊的变量及函数,存在于全局命名空间里. 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应 ...

  5. 智能合约语言 Solidity 教程系列1 - 类型介绍

    现在的Solidity中文文档,要么翻译的太烂,要么太旧,决定重新翻译下.尤其点名批评极客学院名为<Solidity官方文档中文版>的翻译,机器翻译的都比它好,大家还是别看了. 写在前面 ...

  6. Go语言打造以太坊智能合约测试框架(level3)

    传送门: 柏链项目学院 第三课 智能合约自动化测试 之前课程回顾 我们之前介绍了go语言调用exec处理命令行,介绍了toml配置文件的处理,以及awk处理文本文件获得ABI信息.我们的代码算是完成了 ...

  7. Go语言打造以太坊智能合约测试框架(level2)

    传送门: 柏链项目学院 第二课 智能合约自动化编译 前期内容回顾 之前我们的介绍的是如何通过solc编译智能合约,并且调用智能合约,本节我们继续实践,将智能合约的代码自动化编译以及abi文件生成搞定. ...

  8. Go-Ethereum 1.7.2 结合 Mist 0.9.2 实现代币智能合约的实例

    目录 目录 1.什么是 Mist 2.Mist 在哪里下载? 3.Mist 有哪些依赖? 4.如何安装 Mist? 4.1.安装 Mist 依赖工具包 4.2.安装 Mist 4.3.启动 Mist, ...

  9. [转]EOS智能合约 & 私链激活 & 基本操作

    链接:https://www.jianshu.com/p/90dea623ffdf 简介 本篇文章,将跟大家介绍eos私链的激活.基础智能合约的安装,以及为大家演示转账等基础操作.还没有安装eos私链 ...

随机推荐

  1. 机器学习:模型泛化(岭回归:Ridge Regression)

    一.基础理解 模型正则化(Regularization) # 有多种操作方差,岭回归只是其中一种方式: 功能:通过限制超参数大小,解决过拟合或者模型含有的巨大的方差误差的问题: 影响拟合曲线的两个因子 ...

  2. Spark Tungsten in-heap / off-heap 内存管理机制--待整理

    一:Tungsten中到底什么是Page? 1. 在Spark其实不存在Page这个类的.Page是一种数据结构(类似于Stack,List等),从OS层面上讲,Page代表了一个内存块,在Page里 ...

  3. 关联,聚合和组合(复合)--Association, Aggregation and Composition

    概要 Association, Aggregation and Composition are terms that represent relationships among objects. Th ...

  4. vue开发后台管理系统小结

    最近工作需要用vue开发了后台管理系统,由于是第一次开发后台管理系统,中间也遇到了一些坑,想在这里做个总结,也算是对于自己工作的一个肯定.我们金融性质的网站所以就不将代码贴出来哈 一.项目概述 首先工 ...

  5. python爬虫(7)--Beautiful Soup的用法

    1.Beautiful Soup简介 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据. Beautiful Soup提供一些简单的.python式的函数用来 ...

  6. Eclipse中,将jar包导入为User Library

    项目右键 Properties -> bulid path -> Add Library -> User Library -> User Libraries -> New ...

  7. Win 2008 R2安装SQL Server 2008“性能计数器注册表配置单元一致性”失败的解决办法

    Win 2008 R2安装SQL Server 2008“性能计数器注册表配置单元一致性”失败的解决办法(2011-02-23 19:37:32) 转载▼   今天在惠普服务器上安装数据库2008时, ...

  8. [gist]Android SHA-1

    参考:http://stackoverflow.com/questions/5980658/how-to-sha1-hash-a-string-in-android 代码:

  9. Socket编程--基础(基本server/client实现)

    IPv4套接口地址结构 IPv4套接口地址结构通常也称为“网际套接字地址结构”,它以“sockaddr_in”命名,定义在头文件中 LINUX结构下的常用结构,一般创建套接字的时候都要将这个结构里面的 ...

  10. 【Java学习】Java泛型详解

    1. 概述 在引入范型之前,Java类型分为原始类型.复杂类型,其中复杂类型分为数组和类.引入范型后,一个复杂类型就可以在细分成更多的类型.例如原先的类型List,现在在细分成List<Obje ...